package com.mes.schedule.manager;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.annotation.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.annotations.ColumnTransformers;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.mes.basicdata.dao.DeviceDao;
import com.mes.basicdata.dao.WorkCenterDao;
import com.mes.basicdata.domain.OperationDevice;
import com.mes.basicdata.domain.WorkCenter;
import com.mes.common.domain.BasicModel;
import com.mes.common.exception.bo.BaseBusinessException;
import com.mes.common.exception.db.BaseDBException;
import com.mes.common.manager.BasicManager;
import com.mes.common.model.ObjectOperation;
import com.mes.common.spring.SpringUtils;
import com.mes.common.util.IdentityGenerator;
import com.mes.common.util.MMSystemSession;
import com.mes.common.util.SysUtil;
import com.mes.prepare.manager.PrepareTaskManager;
import com.mes.schedule.algorithm.LinkLagCal;
import com.mes.schedule.algorithm.PriorityCalc;
import com.mes.schedule.dao.SOperationTaskDao;
import com.mes.schedule.dao.SPartTaskDao;
import com.mes.schedule.dao.STaskDao;
import com.mes.schedule.domain.McDevice;
import com.mes.schedule.domain.ResourceConstraint;
import com.mes.schedule.domain.SCalendar;
import com.mes.schedule.domain.SDevice;
import com.mes.schedule.domain.SGroupOperationTask;
import com.mes.schedule.domain.SOperationLink;
import com.mes.schedule.domain.SOperationTask;
import com.mes.schedule.domain.SParallelGroup;
import com.mes.schedule.domain.SPartTask;
import com.mes.schedule.domain.SSerialGroup;
import com.mes.schedule.domain.STask;
import com.mes.schedule.domain.STempOperationTask;
import com.mes.schedule.domain.SVirtualLink;
import com.mes.schedule.domain.SWorkCenter;
import com.mes.schedule.domain.ScheduleEvent;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.schedule.manager.iface.IScheduleOperationTaskManager;
import com.mes.schedule.util.ScheduleUtils;
import com.mes.schedule.util.StringOper;
import com.mes.task.dao.OperationTaskDao;
import com.mes.task.domain.OperationTask;
import com.mes.task.manager.AssignmentDeviceManager;
import com.mes.task.manager.OperationTaskManager;
import org.apache.commons.lang.*;

@Component("scheduleOperationTaskManager")
@Transactional
public class ScheduleOperationTaskManager extends BasicManager implements IScheduleOperationTaskManager{
	@Resource
	public SOperationTaskDao scheduleOperationTaskDao;
	@Resource
	public OperationTaskDao operationTaskDao;
	@Resource
	private OperationTaskManager operationTaskManager;
	@Resource
	private STaskDao STaskDao;
	@Resource
	private DeviceDao deviceDao;
	@Resource
	private LinkLagCal linkLagCal;
	@Resource
	public ScheduleLinkManager scheduleLinkManager;
	@Resource
	private ScheduleCalendarManager scheduleCalendarManager;
	@Resource
	private PriorityCalc priorityCalc;
	@Resource
	private ScheduleEventManager scheduleEventManager;
	@Resource
	private ScheduleDeviceManager scheduleDeviceManager;
	@Resource
	private WorkCenterDao workCenterDao;
	@Resource
	private SPartTaskDao schedulePartTaskDao;
	@Resource
	private SchedulePartTaskManager schedulePartTaskManager;
	@Resource
	private ScheduleOperationRecordManager scheduleOperationRecordManager;

	// 缺省暂停延搁时间，单位为分钟
	// 至少应该大于预分配时可留空闲
	// 缺省为2小时
	private final static int Default_Pause_Delay = 60;
	// 缺省暂停延搁时间，缺省为一个班次，8小时
	private final static int Default_Interrupt_Delay = 240;

	public final static Log log = LogFactory
			.getLog(ScheduleOperationTaskManager.class);

	private Boolean controlPrepareTaskInSchedule;

	// 放在这里不合适
	// todo
	private AssignmentDeviceManager assignmentDeviceManager;

	public PrepareTaskManager prepareTaskManager;

	/**
	 * 最大协作工序距离
	 */
	private Integer maxCoTaskPublishDistance;
	/**
	 * 允许发布协作任务的最早开始时间
	 */
	private Boolean allowPublishCoTaskEarlyStart = true;
	/**
	 * 采用零组件任务交货期作为协作任务交货期
	 */
	private Boolean coTaskUsePartTaskLateFinish = false;

	public Boolean getCoTaskUsePartTaskLateFinish() {
		return coTaskUsePartTaskLateFinish;
	}

	public void setCoTaskUsePartTaskLateFinish(
			Boolean coTaskUsePartTaskLateFinish) {
		this.coTaskUsePartTaskLateFinish = coTaskUsePartTaskLateFinish;
	}

	public Boolean getAllowPublishCoTaskEarlyStart() {
		return allowPublishCoTaskEarlyStart;
	}

	public void setAllowPublishCoTaskEarlyStart(
			Boolean allowPublishCoTaskEarlyStart) {
		this.allowPublishCoTaskEarlyStart = allowPublishCoTaskEarlyStart;
	}

	public void setControlPrepareTaskInSchedule(
			Boolean controlPrepareTaskInSchedule) {
		this.controlPrepareTaskInSchedule = controlPrepareTaskInSchedule;
	}

	public Integer getMaxCoTaskPublishDistance() {
		return maxCoTaskPublishDistance;
	}

	public void setMaxCoTaskPublishDistance(Integer maxCoTaskPublishDistance) {
		this.maxCoTaskPublishDistance = maxCoTaskPublishDistance;
	}

	/**
	 * @param taskDao
	 *            the taskDao to set
	 */
	public void setScheduletaskDao(STaskDao STaskDao) {
		this.STaskDao = STaskDao;

	}

	/**
	 * 决定调度过程中的物流移动方式
	 * 
	 * @param link
	 */
	public void decideFlowMode(SOperationLink link) {

		SOperationTask predTask = link.getPredOperationTask();
		SOperationTask operationTask = link.getSuccOperationTask();

		ScheduleScheme scheme = operationTask.getScheme();

		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals(
					"5ff0fa53-6575-4b93-ba07-4beab8b0bde4")

			) {
				log.debug(operationTask);
			}
		}

		// 是否自动平顺
		boolean allowAutoFlow = scheme.getAllowAutoFlow() == null ? false
				: scheme.getAllowAutoFlow();
		double autoFlowSlack = scheme.getAutoFlowSlack() == null ? 1 : scheme
				.getAutoFlowSlack();

		boolean allowAutoPS = scheme.getAllowAutoPS() == null ? false : scheme
				.getAllowAutoPS();

		double autoPSSlack = scheme.getAutoPSSlack() == null ? 2 : scheme
				.getAutoPSSlack();
		if (!(link instanceof SVirtualLink)) {// 非虚拟链接才计算

			if ((link.getLocked() == null) || !link.getLocked()) {
				// 赋初始化值
				link.setMoveType(SOperationLink.MOVETYPE_SEQUENCE);// 顺序操作
				Long l = Math.round(operationTask.getPlanQty());
				link.setTransferQty(l.intValue());
				// 自动平顺
				// 必须在大于0的情况下，保证延迟时间
				if (predTask.getMasterShop() != null
						&& operationTask.getMasterShop() != null
						&& predTask.getMasterShop().startsWith(
								scheme.getDeptUid())
						&& operationTask.getMasterShop().startsWith(
								scheme.getDeptUid())
						&& operationTask.getEstiRunTime() > 0) {
					// 执行平顺的条件
					// 执行流水操作的条件,应该参数化

					// || (predTask.getPlanFinish() != null
					// && predTask.getControlFinish() != null && (predTask
					// .getControlFinish().getTime()
					// - predTask.getPlanFinish().getTime() < 1000 * 60 * 1440 *
					// 5))

					if (allowAutoFlow
							&& (operationTask.getSlackFactor() <= autoFlowSlack)) {
						link.setMoveType(SOperationLink.MOVETYPE_FLOW);// 平行操作
						link.setTransferQty(1);

					} else if (allowAutoPS == true
							&& operationTask.getSlackFactor() <= autoPSSlack) {
						link.setMoveType(SOperationLink.MOVETYPE_FLOWSEQUENCE);// 平顺操作
						// 平顺现在都采取逆退，所以转移数量无所谓
						link.setTransferQty(1);

					}

				}
			}

		}
	}

	/**
	 * 计算工序任务的工艺上的最早开始时间 与计算controlEarlyStart最大的区别是为了在不考虑设备虚拟链接情况下计算工序的等待时间
	 * 
	 * @param operationTask
	 * @return
	 */
	public Date getRealControlEarlyStart(SOperationTask operationTask) {
		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals(
					"38222f23-cf46-4335-bbba-0179389f0fd8")

			) {
				log.debug(operationTask);
			}
		}

		ScheduleScheme scheme = operationTask.getScheme();
		// 最小设置成当前时间
		operationTask.setControlEarlyStart(scheme.getScheduleCurrentTime());

		// 设置计算的必须开始时间段
		// lqm todo
		// 未对固定约束的必须开始时间进行考虑
		operationTask.setCalMustStartSegment(null);

		// 最早开始时间earlystart的限制
		// earlystart一般由人工进行输入
		if (operationTask.getEarlyStart() != null
				&& operationTask.getEarlyStart().after(
						operationTask.getControlEarlyStart()))
			operationTask.setControlEarlyStart(operationTask.getEarlyStart());

		long earlyStart = operationTask.getControlEarlyStart().getTime();

		long temp = 0;
		for (SOperationLink predLink : operationTask.getPredLinkSet()) {

			// 与计算controlStart最大的不同
			if (predLink.getVirtualLink())
				continue;

			SOperationTask predTask = predLink.getPredOperationTask();
			if (predTask.isFinished())
				continue;

			// 由于锁定引起的 前道工序未做完，后道工序开工的现象
			if (predTask.getAssignState() != SOperationTask.ASSNSTATE_SUCCESS
					|| predTask.getPlanStart() == null
					|| predTask.getPlanFinish() == null) {
				// log.debug("前道工序还未排完，可能存在锁定工序先排！"+predTask.getTaskUid());
				break;// 直接返回，因为值已经写入controlEarlyStart
			}
			// 用clone防止更新
			// 用clone防止更新
			SOperationLink link = null;

			try {
				link = (SOperationLink) predLink.clone();
			} catch (CloneNotSupportedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			this.decideFlowMode(link);

			if (link.getLinkLag() == null)
				link.setLinkLag(0);

			switch (link.getMoveType()) {
			case SOperationLink.MOVETYPE_SEQUENCE: {
				temp = predTask.getPlanFinish().getTime()
						+ (long) link.getLinkLag() * 60000;
				break;
			}
			case SOperationLink.MOVETYPE_FLOW: {
				// 暂时流水加工也采用这种计算
				// 存在误差 todo
				// 存在误差
				// if (predTask.getCompleteQty() > 0) {
				// // lqm todo
				// // 待考虑
				// //应该加入是否满足平顺数量
				// temp = predTask.getPlanStart().getTime()
				// + scheduleLinkManager.calPSLag(link);
				// } else {
				temp = predTask.getPlanStart().getTime()
						+ scheduleLinkManager.calFlowLag(link);

				// 如果是锁定的链接方式，则必须在指定时间段开始
				if (link.getLocked() != null && link.getLocked()) {
					operationTask.setCalMustStartSegment(scheme
							.calSegementFromDate(temp));
				}
				// }

				break;
			}
			case SOperationLink.MOVETYPE_FLOWSEQUENCE: {
				// if (predTask.getCompleteQty() > 0) {
				// // lqm todo
				// // 待考虑
				// // lqm todo
				// // 待考虑
				// //应该加入是否满足转移数量
				// temp = predTask.getPlanStart().getTime()
				// + scheduleLinkManager.calPSLag(link);
				// } else {
				temp = predTask.getPlanStart().getTime()
						+ scheduleLinkManager.calPSLag(link);
				// 如果是锁定的链接方式，则必须在指定时间段开始
				if (link.getLocked() != null && link.getLocked()) {
					operationTask.setCalMustStartSegment(scheme
							.calSegementFromDate(temp));
				}
				// }
				break;
			}
			case SOperationLink.MOVETYPE_INGORE: {
				// 不能进行=0处理，防止多个连接时忽略了其它链接的影响
				// temp = 0;// 忽略此链接
				break;
			}
			default: {
				// 缺省为顺序加工
				temp = predTask.getPlanFinish().getTime()
						+ (long) link.getLinkLag() * 60000;
				break;
			}
			}
			// 这一段代码非常有用，千万不要删除
			// todo
			// switch (link.getLinkType()) {
			// case SOperationLink.LINKTYPE_FTS: {
			// if (allowAutoPS == true
			// && operationTask.getPriority() <= autoPSTaskLevel
			// && operationTask.getSlackFactor() <= autoPSSlack
			// && !predTask.isCooperated()
			// && !operationTask.isCooperated()) {
			// temp=predTask.getPlanStart().getTime()+scheduleLinkManager.calPSLag(link);
			// } else {
			// temp = predTask.getPlanFinish().getTime()
			// + (long) link.getLinkLag() * 60000;
			// }
			// // 增加判断是否平顺
			// break;
			// }
			// case SOperationLink.LINKTYPE_STS: {
			// if (predTask.getPlanStart() != null) {
			// temp = predTask.getPlanStart().getTime()
			// + (long) link.getLinkLag() * 60000;
			// }
			// break;
			// }

			// case SOperationLink.LINKTYPE_FTF: {
			// temp = predTask.getPlanFinish().getTime()
			// + ((long) link.getLinkLag() - (long) (operationTask
			// .getEstiTaskWork()) * 60000);
			// break;
			// }
			// case SOperationLink.LINKTYPE_STF: {
			// temp = predTask.getPlanStart().getTime()
			// + (long) (link.getLinkLag() - operationTask
			// .getEstiTaskWork() * 60000);
			// break;
			// }
			// default:
			// break;
			// }

			if (earlyStart <= temp) {
				earlyStart = temp;
			}
		}

		return new Date(earlyStart);

	}

	/**
	 * 计算工序任务的最早开始时间 同时里面蕴含了一个逻辑，平顺， 所以这个方法应该提前进行计算，非常重要
	 * 
	 * @param operationTask
	 * @return
	 */
	public void calcControlEarlyStart(SOperationTask operationTask) {
		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals(
					"90f8dd75-6bdc-4510-b71d-fae234fc117c")) {
				log.debug(operationTask);
			}
		}

		ScheduleScheme scheme = operationTask.getScheme();
		// 最小设置成当前时间
		operationTask.setControlEarlyStart(scheme.getScheduleCurrentTime());
		// 最早开始时间earlystart的限制
		// earlystart一般由人工进行输入
		if (operationTask.getEarlyStart() != null
				&& operationTask.getEarlyStart().after(
						operationTask.getControlEarlyStart()))
			operationTask.setControlEarlyStart(operationTask.getEarlyStart());

		// 同时考虑零件任务的最早开始时间
		if (operationTask.getParentTask() != null) {
			SPartTask partTask = operationTask.getParentTask();
			if (partTask.getControlEarlyStart() != null
					&& partTask.getControlEarlyStart().after(
							operationTask.getControlEarlyStart()))
				operationTask.setControlEarlyStart(partTask
						.getControlEarlyStart());
		}

		// 设置计算的必须开始时间段
		// lqm todo
		// 未对固定约束的必须开始时间进行考虑
		operationTask.setCalMustStartSegment(null);

		long earlyStart = operationTask.getControlEarlyStart().getTime();

		long temp = 0;
		for (SOperationLink link : operationTask.getPredLinkSet()) {
			SOperationTask predTask = link.getPredOperationTask();
			if (predTask.isFinished())
				continue;

			// 由于锁定引起的 前道工序未做完，后道工序开工的现象
			if (predTask.getAssignState() != SOperationTask.ASSNSTATE_SUCCESS
					|| predTask.getPlanStart() == null
					|| predTask.getPlanFinish() == null) {
				// log.debug("前道工序还未排完，可能存在锁定工序先排！"+predTask.getTaskUid());
				break;// 直接返回，因为值已经写入controlEarlyStart
			}
			// 物流方式 从上道到当道工序
			this.decideFlowMode(link);

			if (link.getLinkLag() == null)
				link.setLinkLag(0);

			switch (link.getMoveType()) {
			case SOperationLink.MOVETYPE_SEQUENCE: {
				temp = predTask.getPlanFinish().getTime()
						+ (long) link.getLinkLag() * 60000;
				break;
			}
			case SOperationLink.MOVETYPE_FLOW: {
				// 暂时流水加工也采用这种计算
				// 存在误差 todo
				// 存在误差
				// if (predTask.getCompleteQty() > 0) {
				// // lqm todo
				// // 待考虑
				// //应该加入是否满足平顺数量
				// temp = predTask.getPlanStart().getTime()
				// + scheduleLinkManager.calPSLag(link);
				// } else {
				temp = predTask.getPlanStart().getTime()
						+ scheduleLinkManager.calFlowLag(link);

				// 如果是锁定的链接方式，则必须在指定时间段开始
				// 主要是影响平顺移动时的倒推工作
				// if (link.getLocked() != null && link.getLocked()) {
				operationTask.setCalMustStartSegment(scheme
						.calSegementFromDate(temp));
				// }
				// }

				break;
			}
			case SOperationLink.MOVETYPE_FLOWSEQUENCE: {
				// if (predTask.getCompleteQty() > 0) {
				// // lqm todo
				// // 待考虑
				// // lqm todo
				// // 待考虑
				// //应该加入是否满足转移数量
				// temp = predTask.getPlanStart().getTime()
				// + scheduleLinkManager.calPSLag(link);
				// } else {
				// by lqm todo
				// 2014-08-26
				// 这里在不考虑日历的情况下进行平顺时间的考虑，会导致计算出的开始时间刚好位于 日历空闲阶段
				// 排产时又考虑日历，很容易造成失去平顺效果
				// 所以这里就直接采用平行加工的最早开始时间
				// 最后由最早完成时间来倒推形成平顺效果
				temp = predTask.getPlanStart().getTime()
						+ scheduleLinkManager.calFlowLag(link);
				// temp = predTask.getPlanStart().getTime()
				// + scheduleLinkManager.calPSLag(link);

				// 这样下面导致的必须要用的时间段也不能用了

				// // 如果是锁定的链接方式，则必须在指定时间段开始
				// if (link.getLocked() != null && link.getLocked()) {
				// operationTask.setCalMustStartSegment(scheme
				// .calSegementFromDate(temp));
				// }
				// // }
				break;
			}
			case SOperationLink.MOVETYPE_INGORE: {
				// 不能进行=0处理，防止多个连接时忽略了其它链接的影响
				// temp = 0;// 忽略此链接
				break;
			}
			default: {
				// 缺省为顺序加工
				temp = predTask.getPlanFinish().getTime()
						+ (long) link.getLinkLag() * 60000;
				break;
			}
			}
			// 这一段代码非常有用，千万不要删除
			// todo
			// switch (link.getLinkType()) {
			// case SOperationLink.LINKTYPE_FTS: {
			// if (allowAutoPS == true
			// && operationTask.getPriority() <= autoPSTaskLevel
			// && operationTask.getSlackFactor() <= autoPSSlack
			// && !predTask.isCooperated()
			// && !operationTask.isCooperated()) {
			// temp=predTask.getPlanStart().getTime()+scheduleLinkManager.calPSLag(link);
			// } else {
			// temp = predTask.getPlanFinish().getTime()
			// + (long) link.getLinkLag() * 60000;
			// }
			// // 增加判断是否平顺
			// break;
			// }
			// case SOperationLink.LINKTYPE_STS: {
			// if (predTask.getPlanStart() != null) {
			// temp = predTask.getPlanStart().getTime()
			// + (long) link.getLinkLag() * 60000;
			// }
			// break;
			// }

			// case SOperationLink.LINKTYPE_FTF: {
			// temp = predTask.getPlanFinish().getTime()
			// + ((long) link.getLinkLag() - (long) (operationTask
			// .getEstiTaskWork()) * 60000);
			// break;
			// }
			// case SOperationLink.LINKTYPE_STF: {
			// temp = predTask.getPlanStart().getTime()
			// + (long) (link.getLinkLag() - operationTask
			// .getEstiTaskWork() * 60000);
			// break;
			// }
			// default:
			// break;
			// }

			if (earlyStart <= temp) {
				earlyStart = temp;
			}
		}
		if (operationTask.getTaskUid() == "b8047cec-346c-4e10-88d2-0c025ccb7af5") {
			operationTask.setControlEarlyStart(new Date(earlyStart));
		}

		operationTask.setControlEarlyStart(new Date(earlyStart));

		// todo
		// 其实锁定任务需要一个lockstart的字段，保留用户的lockstart信息，因为planstart会发生变化
		// 锁定任务也必须满足前后道工序的限制
		// 对于锁定任务，设置为其计划开始时间

		// 自动按照计划开始时间向后拖
		if (1 == operationTask.getLocked()
				&& operationTask.getPlanStart() != null
				&& operationTask.getPlanStart().after(
						operationTask.getControlEarlyStart()))
			operationTask.setControlEarlyStart(operationTask.getPlanStart());

		operationTask.setControlEarlyStartSegment(scheme
				.calSegementFromDate(operationTask.getControlEarlyStart()));
		log.debug(operationTask + " 最早开始时间为"
				+ operationTask.getControlEarlyStart());
		// return new Date(earlyStart);

	}

	/*
	 * ȡ��ƽ˳״̬�µ����翪ʼʱ��
	 */
	// private Date getControlEarlyStartOfPSOperation(SOperationTask
	// operationTask) {
	//
	// int transferCount = operationTask.getParentTask().getTransferCount() <= 0
	// ? 1
	// : operationTask.getParentTask().getTransferCount();
	// long temp = 0;
	// for (SOperationLink link : operationTask.getPredLinkSet()) {
	// SOperationTask tempTask = link.getPredOperationTask();
	// SOperationTask predTask = null;
	// if (tempTask.getParentTask() == operationTask.getParentTask()) {
	// predTask = tempTask;
	// } else {
	// break;
	// }
	// if (predTask.isCooperated() == true) {
	// return getControlStartOfSequenceOperation(operationTask);
	// } else {
	// if (predTask.getEstiRunTime() <= operationTask.getEstiRunTime()) {
	// temp = predTask.getPlanStart().getTime()
	// + (long) (predTask.getEstiPreTime()
	// + predTask.getEstiRunTime() * transferCount
	// + link.getLinkLag() - operationTask
	// .getEstiPreTime()) * 60000;
	// } else {
	// temp = predTask.getPlanFinish().getTime()
	// + (long) (operationTask.getEstiRunTime()
	// * transferCount - operationTask
	// .getEstiTaskWork()) * 60000;
	// }
	// }
	// }
	//
	// return new Date(temp);
	// }
	//
	// /*
	// * ȡ��˳��ӹ�״̬�µ����翪ʼʱ��
	// */
	// private Date getControlStartOfSequenceOperation(SOperationTask
	// operationTask) {
	// ScheduleScheme scheme=operationTask.getScheme();
	// //对当前时间的限制
	// //限制最早开始时间
	//
	//
	// Calendar calendar = Calendar.getInstance();
	// operationTask.setControlStart(calendar.getTime()) ;
	// if (operationTask.getEarlyStart()!= null
	// || operationTask.getEarlyStart()
	// .after(operationTask.getControlStart()))
	// operationTask.setControlStart(operationTask.getEarlyStart());
	//
	//
	// boolean allowAutoPS =scheme.getAllowAutoPS() == null ? false
	// : scheme.getAllowAutoPS();
	// int autoPSTaskLevel = operationTask.getScheme()
	// .getAutoPSTaskLevel() == null ? 1 : operationTask
	// .getScheme().getAutoPSTaskLevel();
	// double autoPSSlack = 0;
	// long earlyStart = operationTask.getEarlyStart().getTime();
	// for (SOperationLink link : operationTask.getPredLinkSet()) {
	// SOperationTask predTask = link.getPredOperationTask();
	// //由于锁定引起的 前道工序未做完，后道工序开工的现象
	// if(predTask.getPlanStart()==null || predTask.getPlanFinish()==null)
	// {
	// // log.debug("前道工序还未排完，可能存在锁定工序先排！"+predTask.getTaskUid());
	// return operationTask.getEarlyStart();//用最早开始作为控制开始
	// }
	//
	//
	// long temp=0;
	// switch (link.getLinkType()) {
	// case SOperationLink.LINKTYPE_FTS: {
	// if (allowAutoPS == true && operationTask.getPriority() <= autoPSTaskLevel
	// && operationTask
	// .getSlackFactor() <=
	// autoPSSlack&&!predTask.isCooperated()&&!operationTask.isCooperated())
	// {
	// int transferCount = link.getTransferQty() <= 0 ? 1
	// : link.getTransferQty();
	// if (predTask.getEstiRunTime() <= operationTask.getEstiRunTime()) {
	// temp = predTask.getPlanStart().getTime()
	// + (long) (predTask.getEstiPreTime()
	// + predTask.getEstiRunTime() * transferCount
	// + link.getLinkLag() - operationTask
	// .getEstiPreTime()) * 60000;
	// } else {
	// temp = predTask.getPlanFinish().getTime()
	// + (long) (operationTask.getEstiRunTime()
	// * transferCount - operationTask
	// .getEstiTaskWork()) * 60000;
	// }
	// }
	// else
	// {
	// temp = predTask.getPlanFinish().getTime()
	// + (long) link.getLinkLag() * 60000;
	// }
	// //增加判断是否平顺
	// break;
	// }
	// case SOperationLink.LINKTYPE_STS: {
	// if (predTask.getPlanStart() != null) {
	// temp = predTask.getPlanStart().getTime()
	// + (long) link.getLinkLag()* 60000;
	// }
	// break;
	// }
	// case SOperationLink.LINKTYPE_FTF: {
	// temp = predTask.getPlanFinish().getTime()
	// + ((long) link.getLinkLag() - (long) (operationTask
	// .getEstiTaskWork()) * 60000);
	// break;
	// }
	// case SOperationLink.LINKTYPE_STF: {
	// temp = predTask.getPlanStart().getTime()
	// + (long) (link.getLinkLag() - operationTask
	// .getEstiTaskWork() * 60000);
	// break;
	// }
	// default:
	// break;
	// }
	//
	// if (earlyStart < temp) {
	// earlyStart = temp;
	// }
	// }
	// return new Date(earlyStart);
	//
	// }
	public boolean useDevice(SOperationTask operationTask, SDevice device) {

		if (device.getDeviceUid() != null
				&& operationTask.getAlterResourceMap().containsKey(
						device.getDeviceUid()))
			return true;
		return false;
		// if (operationTask.getAlterResourceList().isEmpty()) {
		// return false;
		// } else {
		// for (ResourceConstraint rc : operationTask.getAlterResourceList()) {
		// if (device.getDeviceUid().equals(rc.getDevice().getDeviceUid())) {
		// return true;
		// }
		// }
		// return false;
		// }

	}

	public void calcControlFinish(SOperationTask operationTask) {

		Date controlFinish = operationTask.getParentTask().getControlFinish();
		long temp = 0;
		if (operationTask.getSuccLinkSet() == null) {
			operationTask.setControlFinish(controlFinish);
		} else {
			for (SOperationLink link : operationTask.getSuccLinkSet()) {

				if (link.getSuccOperationTask().getParentTask() == operationTask
						.getParentTask()) {
					SOperationTask succTask = link.getSuccOperationTask();
					temp = (long) (succTask.getControlFinish().getTime() - (link
							.getLinkLag() + succTask.getEstiTaskWork()) * 60000);
				}

				/*
				 * switch (link.getLinkType()) { case
				 * SOperationLink.LINKTYPE_FTS: { break; } case
				 * SOperationLink.LINKTYPE_STS: { break; } case
				 * SOperationLink.LINKTYPE_FTF: { break; } case
				 * SOperationLink.LINKTYPE_STF: { break; } default: break; }
				 */

			}
		}
		operationTask.setControlFinish(new Date(temp));
	}

	/**
	 * 判读一个工序任务是否已经齐套
	 */
	public boolean isReady(SOperationTask operationTask) {
		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals(
					"90f8dd75-6bdc-4510-b71d-fae234fc117c")) {
				log.debug(operationTask);
			}
		}
		if (operationTask.getPredLinkSet() != null
				&& operationTask.getPredLinkSet().size() > 0) {
			for (SOperationLink predLink : operationTask.getPredLinkSet()) {

				SOperationTask predOperationTask = predLink
						.getPredOperationTask();
				if (predOperationTask.getGroupTask() != null)
					predOperationTask = predOperationTask.getGroupTask();

				if (predOperationTask != null
						&& predOperationTask.getTaskScheduleState().equals(
								SOperationTask.TASKSCHEDULESTATE_STARTED)
						&& (!predOperationTask.getAssignState().equals(
								SOperationTask.ASSNSTATE_SUCCESS))
						&& !predOperationTask.isFinished()) {
					return false;
				}
			}
		}
		return true;
	}

	public SOperationTask groupTasks(List<SPartTask> groupPartTasks,
			String OperationIDDesc, Integer groupType) throws Exception {
		if (groupPartTasks.size() != 0) {
			List<SOperationTask> memberTasks = new ArrayList<SOperationTask>();
			for (SPartTask partTask : groupPartTasks) {
				for (SOperationTask operationTask : partTask
						.getOperationTaskList()) {
					if (operationTask.getOperationIdDesc().equals(
							OperationIDDesc)) {
						memberTasks.add(operationTask);
						break;
					}
				}
			}
			if (memberTasks.size() > 1)
				return this.groupTasks(memberTasks, groupType);

		}
		return null;
	}

	public Date calcTaskPlanFinish(SOperationTask operationTask,
			Date planStart, Double estiPreTime, Double estiRunTime,
			Boolean changeOperationangeOperation) {
		ScheduleScheme scheme = operationTask.getScheme();
		if (planStart == null)
			planStart = operationTask.getPlanStart();
		if (estiPreTime == null)
			estiPreTime = operationTask.getEstiPreTime();
		if (estiRunTime == null)
			estiRunTime = operationTask.getEstiRunTime();

		// 已经开始的不计算准备工时
		if (operationTask.getCompleteQty() > 0)
			estiPreTime = 0d;

		int interval = scheme.getScheduleInterval();
		Date planFinish = planStart;
		SDevice device = operationTask.getDevice();
		if (device == null) {
			planFinish = new Date(planStart.getTime()
					+ (long) ((estiPreTime + estiRunTime
							* (operationTask.getPlanQty() - operationTask
									.getCompleteQty())) * 60000));
		} else {
			int startSegment = scheme.calSegementFromDate(planStart);
			if (startSegment < 0)
				startSegment = 1;
			int period = (int) Math.round((estiPreTime + estiRunTime
					* (operationTask.getPlanQty() - operationTask
							.getCompleteQty()))
					/ interval);
			int endSegment = startSegment;
			int count = 0;
			for (int i = startSegment; i < scheme.getTotalSegement(); i++) {
				int segementCalendar = this.scheduleDeviceManager
						.getSegementCalendar(device, i);
				if (segementCalendar == SCalendar.CALENDAR_NOMAL
						|| segementCalendar == SCalendar.CALENDAR_OVERTIME) {
					count++;
					if (count >= period) {
						endSegment = i;
						break;
					}
				}
			}
			planFinish = scheme.calDateFromSegement(endSegment);
		}
		// operationTask.setPlanFinish(planFinish);
		// double estiTaskWork = estiPreTime + estiRunTime
		// * (operationTask.getPlanQty() - operationTask.getCompleteQty());
		// operationTask.setEstiPreTime(estiPreTime);
		// operationTask.setEstiRunTime(estiRunTime);
		// operationTask.setEstiTaskWork(estiTaskWork);
		// if (changeOperationangeOperation) {
		// taskDao.updateOperationHour(operationTask);
		// }
		return planFinish;
	}

	public List<SOperationTask> filter(
			Collection<SOperationTask> operationTaskList, String drawingId,
			String batchNum, Date lateFinish, Integer planGrade,
			Integer priority, String masterShop, String deptId,
			Integer coTaskState) {
		List<SOperationTask> opListForReturn = new ArrayList<SOperationTask>();

		for (SOperationTask operationTask : operationTaskList) {

			if (!StringOper.equals(drawingId, operationTask.getDrawingId()))
				continue;
			if (!StringOper.equals(batchNum, operationTask.getBatchNum()))
				continue;

			if (masterShop != null && !masterShop.equals("")
					&& !masterShop.equals(operationTask.getMasterShop()))
				continue;

			if (coTaskState != null
					&& !operationTask.getCoTaskState().equals(coTaskState))
				continue;

			if (priority != null && priority > 0) {
				int pp = Integer.parseInt(String.valueOf(
						operationTask.getPriority()).substring(0, 1));
				if (!priority.equals(pp))
					continue;
			}

			opListForReturn.add(operationTask);

		}

		// Collections.sort(opListForReturn, new Comparator<Object>() {
		// public int compare(Object o1, Object o2) {
		// SOperationTask so1 = (SOperationTask) o1;
		// SOperationTask so2 = (SOperationTask) o2;
		// int i = 0;
		// if (partTask1.getPriority() > partTask2.getPriority()) {
		// i = 1;
		// }
		// return i;
		// }
		// });

		return opListForReturn;
	}

	@Transactional
	public void cancelGroupTask(SGroupOperationTask groupTask) throws Exception {

		if (groupTask == null)
			return;

		ScheduleScheme scheme = groupTask.getScheme();
		List<SOperationTask> memberTasks = groupTask.getMemberTasks();
		if (memberTasks != null && memberTasks.size() > 0) {
			for (SOperationTask memberTask : memberTasks) {
				memberTask.setGroupTask(null);
				memberTask.setGroupTaskUid(null);
			}
			// 子任务重新进入调度
			this.intoSchedule(memberTasks);
		}
		// 父任务移出调度
		this.outSchedule(groupTask, false);

		scheme.getGroupTaskList().remove(groupTask);

		// 从系统中移除任务都用这种方法
		// todo?
		// 链接？？这样不行，会将任务原生的链接去掉
		// this.removeOperationTask(groupTask);
		// 必须用remove(groupTask.getTaskUid()),而不是remove(groupTask);
		scheme.getAllOperationTaskMap().remove(groupTask.getTaskUid());
		this.delete(groupTask);
		this.update(memberTasks);

	}

	@Transactional
	public SOperationTask addOperationTask(ScheduleScheme scheme,
			SOperationTask so, SPartTask partTask) throws Exception {
		SOperationTask newSo = new SOperationTask();
		if (partTask == null)
			return null;
		ObjectOperation.copyAttributes(so, newSo);
		newSo.setScheme(scheme);
		newSo.setTaskUid(IdentityGenerator.GetIdentityString());
		newSo.setParentTask(partTask);
		newSo.setPartUid(partTask.getPartUid());
		// 设置请制部门
		newSo.setDeptUid(scheme.getDeptUid());
		newSo.setBatchNum(partTask.getBatchNum());
		if (newSo.getTaskState() == null)
			newSo.setTaskState(SOperationTask.TASKSTATE_READY);
		// setTaskMasterShop(newSo);
		newSo.calTaskWork();
		partTask.getOperationTaskList().add(newSo);

		this.calcAlterResourceList(newSo);

		// 创建缺省工序
		// by lqm todo
		// 很无赖的选择，其实这里没有必要产生op,主要是为了能够增加工序限制
		// todo
		// 这条opuid其实专门为了强制设置工序为做，
		// 可以将其移到强制工序中去
		if (newSo.getOpUid() == null) {
			// taskDao.addOperation(newSo);
		}

		if (newSo.getTaskScheduleState() == SOperationTask.TASKSCHEDULESTATE_STARTED)
			this.intoSchedule(newSo);
		scheme.getAllOperationTaskMap().put(newSo.getTaskUid(), newSo);
		// 直接添加到数据库中
		this.add(newSo);

		return newSo;

	}

	public void updateOperationTask(ScheduleScheme scheme,
			SOperationTask newTask) throws Exception {
		log.debug("updateOperationTask更新工序任务 开始" + newTask);
		SOperationTask originalTask = scheme.getAllOperationTaskMap().get(
				newTask.getTaskUid());

		if (originalTask == null)
			throw new Exception("找不到更新的工序任务！" + newTask);
		if (newTask.getPlanStart() != null && newTask.getPlanFinish() != null
				&& newTask.getPlanFinish().before(newTask.getPlanStart()))
			throw new Exception("计划结束时间不能晚于计划开始时间！"
					+ newTask.toFriendlyString());

		// BeanUtils.copyProperties(originalTask, newTask);
		// todo 这里应该执行完成逻辑

		// BeanUtils.copyProperties(dest, orig)

		// originalTask.setPlanStart(newTask.getPlanStart());
		// originalTask.setEarlyStart(newTask.getEarlyStart());
		// originalTask.setLateFinish(newTask.getLateFinish());
		// originalTask.setPlanFinish(newTask.getPlanFinish());
		// originalTask.setEstiPreTime(newTask.getEstiPreTime());
		// originalTask.setEstiRunTime(newTask.getEstiRunTime());
		// originalTask.setLocked(newTask.getLocked());
		// originalTask.setDeviceClass(newTask.getDeviceClass());
		// originalTask.setDeviceClassName(newTask.getDeviceClassName());
		// ����ͼ

		// 处理设备问题&& !(newTask.getDeviceUid().equals(originalTask.getDeviceUid())
		if (newTask.getDeviceUid() != null
				&& !newTask.getDeviceUid().equals(originalTask.getDeviceUid())) {
			if (originalTask.isRunning()) {
				String str = "该工序处于已下发状态，请先取消派工后再进行设备变更！\n"
						+ originalTask.toFriendlyString() + "\n";
				if (originalTask.getDevice() != null)
					str += "当前设备为：" + originalTask.getDevice().getDeviceName();
				throw new Exception(str);
			}
			SDevice device = scheme.getDeviceMap().get(newTask.getDeviceUid());
			if (device != null) {
				originalTask.setDevice(device);
				originalTask.setDeviceUid(device.getDeviceUid());
				// originalTask.setDeviceClass(device.getDeviceClass());
				// originalTask.setDeviceClassName(device.getDeviceClassName());

			}
		}
		if (newTask.getCalUid() == null) {
			originalTask.setCalUid(null);
			originalTask.setCalendar(null);
		} else {
			if (!newTask.getCalUid().equals(originalTask.getCalUid())) {
				String strCalUid = newTask.getCalUid();
				SCalendar scalendar = scheme.getCalendarMap().get(strCalUid);
				if (scalendar == null) {
					scalendar = scheduleCalendarManager.initCalendar(scheme,
							strCalUid);
					// scheme.getCalendarMap().put(strCalUid, scalendar);
				}
				originalTask.setCalUid(strCalUid);
				originalTask.setCalendar(scalendar);
			}
		}

		if (newTask.getDeviceClass() != null
				&& !newTask.getDeviceClass().equals(
						originalTask.getDeviceClass())) {
			originalTask.setDeviceClass(newTask.getDeviceClass());
			originalTask.setDeviceClassName(newTask.getDeviceClassName());
			originalTask.setMasterShop(newTask.getMasterShop());
			originalTask.setMasterShopName(newTask.getMasterShopName());
			// log.debug("updateOperationTask更新工序任务 开始计算可选资源列表！");
			// this.calcAlterResourceList(originalTask);
		}
		if (newTask.getDrawingId() != null)
			originalTask.setDrawingId(newTask.getDrawingId());
		if (newTask.getPartName() != null)
			originalTask.setPartName(newTask.getPartName());
		if (newTask.getBatchNum() != null)
			originalTask.setBatchNum(newTask.getBatchNum());
		if (newTask.getOperationIdDesc() != null)
			originalTask.setOperationIdDesc(newTask.getOperationIdDesc());
		if (newTask.getTaskName() != null)
			originalTask.setTaskName(newTask.getTaskName());
		if (newTask.getOperationId() > 0)
			originalTask.setOperationId(newTask.getOperationId());

		originalTask.setPlanStart(newTask.getPlanStart());
		originalTask.setPlanFinish(newTask.getPlanFinish());
		originalTask.setEarlyStart(newTask.getEarlyStart());
		originalTask.setLateFinish(newTask.getLateFinish());
		originalTask.setActualStart(newTask.getActualStart());
		originalTask.setDeviceSeq(newTask.getDeviceSeq());
		originalTask.setEstiPreTime(newTask.getEstiPreTime());
		originalTask.setEstiRunTime(newTask.getEstiRunTime());
		originalTask.setEstiDelayTime(newTask.getEstiDelayTime());
		originalTask.setLocked(newTask.getLocked());
		// 调度任务处理
		if (newTask.getTaskScheduleState() != originalTask
				.getTaskScheduleState()) {
			if (newTask.getTaskScheduleState() == SOperationTask.TASKSCHEDULESTATE_STARTED)
				this.intoSchedule(originalTask);
			else if (newTask.getTaskScheduleState() == SOperationTask.TASKSCHEDULESTATE_WAITING)
				this.outSchedule(originalTask, null);
		}
		originalTask.setCanSplit(newTask.getCanSplit());
		originalTask.setNotes(newTask.getNotes());

		originalTask.setPlanQty(newTask.getPlanQty());

		// originalTask.setCompleteQty(newTask.getCompleteQty());

		if (newTask.getCompleteQty() != originalTask.getCompleteQty()) {
			this.feedbackTask(scheme, originalTask, newTask.getCompleteQty()
					- originalTask.getCompleteQty(), newTask.getDeviceUid(),
					scheme.getScheduleCurrentTime());
		}

		// ObjectOperation.copyAttributes(newTask, originalTask);

		// List<ResourceConstraint>
		// resourceDeviceList=originalTask.getAlterResourceList();
		// scheduleScheme.getOperationDeviceList();//kaolv

		originalTask.calTaskWork();
		// 取消工时更新
		// taskDao.updateOperationHour(originalTask);

		if (newTask.getCompleteQty() != null && newTask.getPlanQty() != null
				&& newTask.getCompleteQty() >= newTask.getPlanQty()) {
			this.completeTask(scheme, originalTask);
		}

		log.debug("updateOperationTask更新工序任务 开始计算可选资源列表！");
		// 因为修改工时序列，锁定，任务状态，工作中心，设备信息等都可能导致可选设备变更，所以
		// 就放在这里恒执行了
		this.calcAlterResourceList(originalTask);

		this.update(originalTask);

		log.debug("updateOperationTask更新工序任务 结束" + newTask);
	}

	private void setTaskMasterShop1(SOperationTask so) {
		// // todo
		// // 非常专用，拟重做
		// if ("cooperationCenter".equals(so.getDeviceClass()))
		// so.setMasterShop("WX");
		// else {
		// log.debug("setTaskMasterShop 工序scheme" + so.getScheme());
		// log.debug("setTaskMasterShop 工序部门编号" + so.getScheme().getDeptUid());
		// so.setMasterShop(so.getScheme().getDeptUid());
		// }
	}

	// 计算获取工序任务列表
	// todo
	// 代码需要整理
	// 如果没有则新建限制
	private ResourceConstraint getResourceConstraint(
			SOperationTask operationTask, SDevice scheduleDevice) {

		if (operationTask.getAlterResourceMap().containsKey(
				scheduleDevice.getDeviceUid()))
			return operationTask.getAlterResourceMap().get(
					scheduleDevice.getDeviceUid());
		// for (ResourceConstraint resourceConstraint :
		// operationTask.getAlterResourceMap().values()) {
		// if (resourceConstraint.getDevice().getDeviceUid().equals(
		// scheduleDevice.getDeviceUid())) {
		// return resourceConstraint;
		// }
		// }

		ResourceConstraint resourceConstraint = new ResourceConstraint(
				operationTask.getTaskUid(), scheduleDevice.getDeviceUid());
		resourceConstraint.setNeedCapability(1);
		resourceConstraint.setDevice(scheduleDevice);
		resourceConstraint.setPriority(3);
		operationTask.getAlterResourceMap().put(scheduleDevice.getDeviceUid(),
				resourceConstraint);
		return resourceConstraint;

	}

	// 计算获取工序任务列表
	// todo
	// 代码需要整理
	public void calcAlterResourceList(SOperationTask operationTask) {
		// if (operationTask.getTaskUid().equals("3306321")) {
		// log.debug("calcAlterResourceList,开始！" + operationTask);
		// }
		log.debug("calcAlterResourceList,开始！" + operationTask);

		if (operationTask.getTaskUid().equals(
				"7aa7cf86-8e8e-4000-a343-1f25d7c619ac")) {
			log.debug("aa");
		}

		operationTask.getAlterResourceMap().clear();
		ScheduleScheme scheme = operationTask.getScheme();

		String deviceClass = operationTask.getDeviceClass();
		if (deviceClass == null
				|| deviceClass.equals("")
				|| deviceClass.equals("cooperationCenter")
				|| (operationTask.getMasterShop() != null && !operationTask
						.getMasterShop().startsWith(scheme.getDeptUid()))) {
			// operationTask.setDeviceClass("cooperationCenter");
			// operationTask.setDeviceClassName("外协中心");
			// operationTask.setMasterShop("WX");
			// operationTask.setMasterShopName("外协");
		} else {

			if (!this.canChangeDevice(operationTask))// 如果锁定，则忽略以前的设备约束
			{
				log.debug("getAlterResourceList,锁定任务直接给定资源！");

				ResourceConstraint rc = new ResourceConstraint(operationTask
						.getTaskUid(), operationTask.getDeviceUid());
				rc.setDevice(operationTask.getDevice());
				rc.setPriority(1);
				operationTask.getAlterResourceMap().put(
						operationTask.getDeviceUid(), rc);
			} else {
				Map<String, SDevice> deviceMap = scheme.getDeviceMap();
				// add device selection constraint
				List<OperationDevice> operDeviceList = scheme
						.getOperationDeviceMap().get(operationTask.getOpUid());
				// 临时判断
				// if(operDeviceList==null)
				// log.info("***工序任务"+operationTask +"设备偏好数量为 空:");
				// else {
				// log.info("***工序任务"+operationTask
				// +"设备偏好数量为:"+operDeviceList.size());
				// }

				// 设置工序任务的缺省工作中心设备
				log.debug("calcAlterResourceList,开始设置缺省工作中心可选队列！"
						+ operationTask + " 工作中心为："
						+ operationTask.getDeviceClass());
				for (SDevice device : deviceMap.values()) {
					// 增加对虚拟设备的判断
					// by lqm 2014-06-05
					// 如果无能力的设备也直接排除
					if (!device.getVirtual()
							&& device.getDeviceClass().equals(
									operationTask.getDeviceClass())) {
						ResourceConstraint resourceConstraint = new ResourceConstraint(
								operationTask.getTaskUid(), device
										.getDeviceUid());

						resourceConstraint.setDevice(device);
						resourceConstraint.setNeedCapability(1);
						resourceConstraint.setSetupTime(operationTask
								.getEstiPreTime());
						resourceConstraint.setRunTime(operationTask
								.getEstiRunTime());
						resourceConstraint.setPriority(3);

						operationTask.getAlterResourceMap().put(
								device.getDeviceUid(), resourceConstraint);
					}
				}

				log.debug("calcAlterResourceList,缺省工作中心可选设备个数为："
						+ operationTask.getAlterResourceMap().size() + ","
						+ operationTask);
				if (operDeviceList != null && operDeviceList.size() > 0) {
					log.debug("calcAlterResourceList,开始设置工序设备限制！设备限制数量为"
							+ operDeviceList.size() + operationTask);

					// boolean bExitLoop = false;

					Collections.sort(operDeviceList,
							new Comparator<OperationDevice>() {

								public int compare(OperationDevice o1,
										OperationDevice o2) {
									int i = 0;
									// 有专有约束排在最后
									if (o1.getApplyTaskUid() != null
											&& !(o1.getApplyTaskUid()
													.equalsIgnoreCase("NA"))) {
										return 1;
									}

									if (o1.getPriority() != null
											&& o2.getPriority() != null
											&& o1.getPriority().compareTo(
													o2.getPriority()) < 0)
										return 1;

									return 0;

								}

							});

					for (OperationDevice operationDevice : operDeviceList) {

						// if (bExitLoop)
						// break;// 防止出现一台设备出现多个约束，比如一个尽可能，一个专属的绝对要安排

						// 判断是否属于只针对某一任务专门的约束
						// 这个任务完成后，应该将其删除
						// todo,将来应该分开
						if (operationDevice.getApplyTaskUid() != null
								&& !(operationDevice.getApplyTaskUid()
										.equalsIgnoreCase("NA"))) {
							if (!(operationDevice.getApplyTaskUid()
									.equals(operationTask.getTaskUid())))
								continue;
							else {
								log.debug("专属约束生效，优先级为："
										+ operationDevice.getPriority()
										+ "设备为：" + operationDevice.getDevice());
							}
						}

						SDevice device = deviceMap.get(operationDevice
								.getDeviceUid());
						if (device == null)
							continue;

						ResourceConstraint currentResourceConstraint = this
								.getResourceConstraint(operationTask, device);
						if (currentResourceConstraint == null)
							continue;
						currentResourceConstraint.setPriority(operationDevice
								.getPriority().intValue());
						if(operationDevice.getEstiPreopTime() == null) 
							currentResourceConstraint.setSetupTime(0.0);
						else
							currentResourceConstraint.setSetupTime(operationDevice
								.getEstiPreopTime());
						if(operationDevice.getEstiRunTime() == null) 
							currentResourceConstraint.setRunTime(0.0);
						else
							currentResourceConstraint.setRunTime(operationDevice
								.getEstiRunTime());		
						switch (operationDevice.getPriority().intValue()) {
						case 1: { // must be processed on the device
							// constraint
							operationTask.getAlterResourceMap().clear();
							operationTask.getAlterResourceMap().put(
									device.getDeviceUid(),
									currentResourceConstraint);
							// bExitLoop = true;
							break;
						}
						case 2: { // has a high priority to process the task
							break;
						}
						case 3: {
							break;
						}
						case 4: { // don't use the device unless no other
							// device
							// available
							break;
						}
						case 5: { // never use this device to process the task
							operationTask.getAlterResourceMap().remove(
									device.getDeviceUid());
							break;
						}
						default:
							break;
						}
					}

				}

			}
		}
		// 如果只有一台设备，则缺省为1
		// todo
		// 应该用常量
		// 1表示必须分派
		if (operationTask.getAlterResourceMap().size() == 1)
			operationTask.getAlterResourceMap().values().iterator().next()
					.setPriority(1);
		else if (operationTask.getAlterResourceMap().size() == 0) { // 如果可选设备为0，则直接利用无限能力设备
			// operationTask.setDeviceClass("cooperationCenter");
			// operationTask.setDeviceClassName("外协中心");
			// operationTask.setMasterShop("WX");
			// operationTask.setMasterShopName("外协");
			ResourceConstraint resourceConstraint = new ResourceConstraint(
					operationTask.getTaskUid(), "cooperation");
			resourceConstraint.setNeedCapability(1);
			resourceConstraint.setSetupTime(operationTask.getEstiPreTime());
			resourceConstraint.setRunTime(operationTask.getEstiRunTime());
			resourceConstraint.setPriority(1);// 必须分到此设备
			SDevice device = scheme.getDeviceMap().get("cooperation");
			resourceConstraint.setDevice(device);
			operationTask.getAlterResourceMap().put("cooperation",
					resourceConstraint);
		}

		log.debug("calcAlterResourceList,结束！" + operationTask);

	}

	public int calcTaskDistance(SOperationTask operationTask) {
		if (operationTask.getPredLinkSet().isEmpty()) {
			return 0;
		} else {
			for (SOperationLink opLink : operationTask.getPredLinkSet()) {
				SOperationTask predTask = opLink.getPredOperationTask();
				if (predTask.getParentTask() == operationTask.getParentTask()) {
					return calcTaskDistance(predTask) + 1;
				}
			}
			return 0;
		}
	}

	public void sortByPriorityTaskDistanceSlack(
			List<SOperationTask> operationTaskList) {
		if (operationTaskList == null || operationTaskList.isEmpty()) {
			return;
		} else {
			Collections.sort(operationTaskList, new Comparator<Object>() {
				public int compare(Object o1, Object o2) {
					SOperationTask operTask1 = (SOperationTask) o1;
					SOperationTask operTask2 = (SOperationTask) o2;
					int i = 0;
					if (operTask1.getParentTask().getPriority() > operTask2
							.getParentTask().getPriority()
							|| (operTask1.getParentTask().getPriority() == operTask2
									.getParentTask().getPriority() && operTask1
									.getTaskDistance() > operTask2
									.getTaskDistance())
							|| (operTask1.getParentTask().getPriority() == operTask2
									.getParentTask().getPriority()
									&& operTask1.getTaskDistance() == operTask2
											.getTaskDistance() && operTask1
									.getSlackFactor() > operTask2
									.getSlackFactor())) {
						i = 1;
					}
					return i;
				}
			});

		}

	}

	public void changeDevice(SOperationTask operationTask, SDevice device)
			throws Exception {
		if (device == null)
			throw new Exception("改变设备时，设备不能为空！");
		operationTask.setDevice(device);
		operationTask.setDeviceUid(device.getDeviceUid());
		operationTask.setDeviceClass(device.getDeviceClass());
		operationTask.setDeviceClassName(device.getDeviceClassName());

		// lqm todo
		// 应该参数化，避免无谓的调整
		// 是否还应该调整队列

	}

	public LinkLagCal getLinkLagCal() {
		return linkLagCal;
	}

	public void setLinkLagCal(LinkLagCal linkLagCal) {
		this.linkLagCal = linkLagCal;
	}

	public ScheduleLinkManager getScheduleLinkManager() {
		return scheduleLinkManager;
	}

	public void setScheduleLinkManager(ScheduleLinkManager scheduleLinkManager) {
		this.scheduleLinkManager = scheduleLinkManager;
	}

	private void netSort(List<SOperationTask> operationTaskList) {
		if (operationTaskList == null || operationTaskList.isEmpty()) {
			return;
		} else {
			Collections.sort(operationTaskList, new Comparator<Object>() {
				public int compare(Object o1, Object o2) {
					SOperationTask operTask1 = (SOperationTask) o1;
					SOperationTask operTask2 = (SOperationTask) o2;
					if (operTask1.getNetDepth() > operTask2.getNetDepth()
							|| (operTask1.getNetDepth() == operTask2
									.getNetDepth() && operTask1
									.getOperationId() > operTask2
									.getOperationId()))
						return 1;
					else
						return 0;

				}
			});

		}

	}

	/*
	 * 这个按照大纲级别的排序还存在问题
	 */
	private void outlineNumberSort(List<SOperationTask> operationTaskList,
			String outlineNumber) {
		if (operationTaskList == null || operationTaskList.isEmpty()) {
			return;
		} else {
			Collections.sort(operationTaskList, new Comparator<Object>() {
				public int compare(Object o1, Object o2) {
					SOperationTask operTask1 = (SOperationTask) o1;
					SOperationTask operTask2 = (SOperationTask) o2;
					int result = 1;
					if (operTask1.getOutlineNumber() == null) {
						if (operTask2.getOutlineNumber() == null)
							if (operTask1.getOperationId() < operTask1
									.getOperationId())
								result = 0;
							else
								result = 0;
					} else if (operTask2.getOutlineNumber() != null) {
						if (getSortNumber(operTask1) < getSortNumber(operTask2))
							result = 0;
					}

					return result;
				}
			});

		}

	}

	private int getSortNumber(SOperationTask so) {
		int s = 1;
		String outlineNumber = so.getOutlineNumber();
		int ipos = outlineNumber.lastIndexOf(".");
		if (ipos < 0) {

			s = Integer.parseInt(outlineNumber);
		} else {
			s = Integer.parseInt(outlineNumber.substring(ipos + 1,
					outlineNumber.length()));
		}

		return s;
	}

	// 按照网络计算的工序距离
	public void calTaskDistance(SPartTask partTask) throws Exception {

		List<SOperationTask> soList = partTask.getOperationTaskList();
		if (soList != null && soList.size() > 1) {

			for (SOperationTask so : soList) {
				if (so.getPredLinkSet() == null
						|| so.getPredLinkSet().size() == 0) {
					calNetDepth(so, 0, soList.size());
				}
			}
		}

	}

	public List<SOperationTask> getOperationTaskListSortByNetDepth(
			ScheduleScheme scheme, String partTaskUid) throws Exception {

		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
		if (partTask == null)
			return null;
		List<SOperationTask> soList = partTask.getOperationTaskList();
		if (soList != null && soList.size() > 1) {
			// todo
			// 每次都要计算有点浪费
			calTaskDistance(partTask);

			netSort(soList);

		}
		return soList;
	}

	/*
	 * validso标识正在校验的工序
	 */
	public void cycleLinkCheck(SOperationTask so, SOperationTask validSo,
			boolean isSucc) throws Exception {
		if (isSucc && so == validSo) {
			throw new Exception("工序号：" + validSo.getOperationIdDesc() + " "
					+ validSo.getTaskName() + " 链接出现循环，请仔细检查");
		}
		for (SOperationLink sl : so.getSuccLinkSet()) {
			if (sl.getSuccOperationTask() != null) {
				cycleLinkCheck(sl.getSuccOperationTask(), validSo, true);
			}

		}
	}

	/**
	 * 返回某一工序任务的前置任务
	 * 
	 * @param operationTask
	 * @param partTask
	 *            指定必须在某一零件任务之中
	 * @return
	 */
	public Set<SOperationTask> getAllPredOperationTasks(
			SOperationTask operationTask, SPartTask partTask) {

		Set<SOperationTask> allPredOperationTasks = new HashSet<SOperationTask>();
		calPredOperationTasks(operationTask, partTask, allPredOperationTasks);
		return allPredOperationTasks;

	}

	public void calPredOperationTasks(SOperationTask operationTask,
			SPartTask partTask, Set<SOperationTask> allPredOperationTasks) {

		for (SOperationLink sl : operationTask.getPredLinkSet()) {
			SOperationTask predOperationTask = sl.getPredOperationTask();
			if (predOperationTask != null) {
				if (partTask != null
						&& !partTask.equals(predOperationTask.getParentTask()))
					continue;
				allPredOperationTasks.add(predOperationTask);
				this.calPredOperationTasks(predOperationTask, partTask,
						allPredOperationTasks);

			}

		}

	}

	private void calNetDepth(SOperationTask so, int netDepth, int maxNetDepth) {
		if (netDepth > maxNetDepth) {
			log.warn("工序链接出现循环，请仔细检查");
			return;// 防止出现链接递归现象
		}
		so.setNetDepth(netDepth);
		// todo
		// 这句话放在这里不太合适
		so.setTaskDistance(netDepth);
		so.setOperationId(new Integer(netDepth).floatValue());// 暂时将其记录在operation_id中，用于下次排序
		// todo
		// 这里应该有父任务的判断
		// 从网络深度上考虑，这个算法是不够的
		for (SOperationLink sl : so.getSuccLinkSet()) {
			if (sl.getSuccOperationTask() != null) {
				calNetDepth(sl.getSuccOperationTask(), netDepth + 1,
						maxNetDepth);
			}

		}
	}

	public void removeOperationTask(ScheduleScheme scheme,
			String operationTaskUid) throws Exception {
		SOperationTask temp = scheme.getAllOperationTaskMap().get(
				operationTaskUid);
		if (temp == null)
			throw new Exception("根据任务唯一号找不到工序任务：" + operationTaskUid);

		removeOperationTask(temp, false);

	}

	/**
	 * hba 添加是否从数据库删除的判断参数
	 * 
	 * @param operationTask
	 * @param isRemovedFromDB
	 * @throws Exception
	 */
	public void removeOperationTask(SOperationTask operationTask,
			Boolean isRemovedFromDB) throws Exception {
		ScheduleScheme scheme = operationTask.getScheme();

		if (operationTask == null)
			throw new Exception("工序任务不能为空！");

		if (operationTask.getGroupTask() != null) {
			this.deleteMemberTask(operationTask.getGroupTask(), operationTask);
		}

		if (SOperationTask.TASKTYPE_TEMPTASK
				.equals(operationTask.getTaskType())) {
			if (scheme.getScheduleTempTaskList().contains(operationTask))
				scheme.getScheduleTempTaskList().remove(operationTask);
		}
		if (SOperationTask.TASKTYPE_COTASK.equals(operationTask.getTaskType())) {
			if (scheme.getCoTaskMap().containsKey(operationTask.getTaskUid()))
				scheme.getCoTaskMap().remove(operationTask.getTaskUid());
		}
		scheduleLinkManager.deletePredLink(operationTask);
		scheduleLinkManager.deleteSuccLink(operationTask);

		if (operationTask.getParentTask() != null
				&& operationTask.getParentTask().getOperationTaskList() != null) {
			operationTask.getParentTask().getOperationTaskList().remove(
					operationTask);
			if (operationTask.getParentTask().getOperationTaskList().size() == 0) {
				SPartTask partTask = operationTask.getParentTask();
				partTask.setTaskState(106);
				schedulePartTaskDao.update(partTask);
				// 有问题，因为在应用工艺时会先清空工序，导致零件任务被删除
				// schedulePartTaskManager.removePartTask(partTask, true);
			}
			// 重新刷新该零件的工序距离

			this.refreshTaskDistance(operationTask);
		}
		if (scheme.getScheduleOperationTasks().contains(operationTask))
			scheme.getScheduleOperationTasks().remove(operationTask);

		if (isRemovedFromDB) {
			this.delete(operationTask);
			scheme.getAllOperationTaskMap().remove(operationTask.getTaskUid());
		} else {
			operationTask.setTaskState(SOperationTask.TASKSTATE_COMPLETED);
			operationTask.setTaskScheduleState(STask.TASKSCHEDULESTATE_NO);
			operationTask.setCompleteQty(operationTask.getPlanQty());
			operationTask.setActualFinish(new Date());
			this.update(operationTask);
		}
		operationTask = null;

	}

	public void justRemoveOperationTask(SOperationTask operationTask)
			throws Exception {
		ScheduleScheme scheme = operationTask.getScheme();

		if (operationTask == null)
			throw new Exception("工序任务不能为空！");

		if (operationTask.getGroupTask() != null) {
			this.deleteMemberTask(operationTask.getGroupTask(), operationTask);
		}

		if (SOperationTask.TASKTYPE_TEMPTASK
				.equals(operationTask.getTaskType())) {
			if (scheme.getScheduleTempTaskList().contains(operationTask))
				scheme.getScheduleTempTaskList().remove(operationTask);
		}
		if (SOperationTask.TASKTYPE_COTASK.equals(operationTask.getTaskType())) {
			if (scheme.getCoTaskMap().containsKey(operationTask.getTaskUid()))
				scheme.getCoTaskMap().remove(operationTask.getTaskUid());
		}
		scheduleLinkManager.deletePredLink(operationTask);
		scheduleLinkManager.deleteSuccLink(operationTask);

		if (operationTask.getParentTask() != null
				&& operationTask.getParentTask().getOperationTaskList() != null) {
			operationTask.getParentTask().getOperationTaskList().remove(
					operationTask);
			// 重新刷新该零件的工序距离

			this.refreshTaskDistance(operationTask);
		}
		if (scheme.getScheduleOperationTasks().contains(operationTask))
			scheme.getScheduleOperationTasks().remove(operationTask);
		scheme.getAllOperationTaskMap().remove(operationTask.getTaskUid());

		operationTask.setActualFinish(scheme.getScheduleCurrentTime());
		operationTask.setTaskState(SPartTask.TASKSTATE_COMPLETED);
		operationTask.setCompleteQty(operationTask.getPlanQty());
		operationTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_NO);
		this.update(operationTask);

		// this.delete(operationTask);

		operationTask = null;

	}

	 
	public Boolean delete(Serializable object) throws Exception {
		SOperationTask so = (SOperationTask) object;
		try {
			SOperationTask persistenceOperationTask = this.scheduleOperationTaskDao
					.getScheduleOperationTask(so.getScheduleUid(), so
							.getTaskUid());
			if (persistenceOperationTask != null) {
				// ObjectOperation.copyAttributes(originalTask,
				// persistenceOperationTask);

				super.delete(persistenceOperationTask);
			}
		} catch (BaseDBException e) {
			// TODO Auto-generated catch block
			throw new BaseBusinessException(e.getMessage());

		}

		return true;

	}

	 
	public Boolean update(Serializable object) throws Exception {
		SOperationTask so = (SOperationTask) object;

		try {
			String pt = so.getParentTaskUid();
			SOperationTask persistenceOperationTask = this.scheduleOperationTaskDao
					.getScheduleOperationTask(so.getScheduleUid(), so
							.getTaskUid());

			if (persistenceOperationTask != null) {
				ObjectOperation.copyAttributes(so, persistenceOperationTask,
						true);
				persistenceOperationTask.setParentTaskUid(pt);
				super.update(persistenceOperationTask);
			}
		} catch (BaseDBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return true;
	}

	public void cancleParallel(SParallelGroup pallelGroup) throws Exception {
		// TODO Auto-generated method stub

	}

	public void parallel(List<SOperationTask> operationTaskList)
			throws Exception {
		// TODO Auto-generated method stub

	}

	public List<SOperationTask> getOperationTaskListSortByOutLineNumber(
			ScheduleScheme scheme, String parentTaskUid) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	public List<SOperationTask> getOperationTaskListByOutlineNumber(
			ScheduleScheme scheme, String partTaskUid, String outlineNumber)
			throws Exception {
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}
		if (outlineNumber == null)
			return null;
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);

		List<SOperationTask> soList = new ArrayList<SOperationTask>();
		{
			for (SOperationTask so : partTask.getOperationTaskList()) {
				if (outlineNumber.equals("0")) {
					if (so.getOutlineNumber() == null
							|| so.getOutlineNumber().indexOf(".") == -1) {
						soList.add(so);
						continue;
					}
				} else {
					if (so.getOutlineNumber() != null
							&& so.getOutlineNumber().startsWith(
									outlineNumber + ".")
							&& so.getOutlineNumber().indexOf(".",
									outlineNumber.length() + 2) == -1)
						soList.add(so);
				}
			}
		}

		if (soList != null && soList.size() > 1) {
			outlineNumberSort(soList, outlineNumber);
		}
		return soList;

	}

	public List<SOperationTask> getOperationTaskList(ScheduleScheme scheme,
			String partTaskUid) throws Exception {
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
		return partTask.getOperationTaskList();
	}

	 
	public void refreshSlackAndColor(ScheduleScheme scheme,
			Collection<? extends SOperationTask> operationTasks)
			throws Exception {
		// TODO Auto-generated method stub
		// by lqm
		// 重新计算松弛率
		if (operationTasks == null || operationTasks.size() == 0)
			return;
		for (SOperationTask operationTask : operationTasks) {
			if (operationTask.getLateFinish() != null) {
				operationTask.setControlFinish(operationTask.getLateFinish());
			} else
				operationTask.setControlFinish(scheme.getScheduleFinish());
			this.calcSlack(operationTask);
		}
		priorityCalc.calcOperationTaskPriority(operationTasks);

	}

	public void calcSlack(SOperationTask operationTask) {
		if (operationTask == null)
			return;

		double slack = 999999;// 很大的松弛率
		operationTask.setSlackFactor(slack);

		Date lateFinish = operationTask.getControlFinish();
		double remainTime = (lateFinish.getTime() - operationTask.getScheme()
				.getScheduleStart().getTime()) / 60000;

		double remainWork = operationTask.getEstiTaskWork();
		if (remainWork > 0) {
			// 松弛率计算公式
			slack = remainTime / remainWork;
			operationTask.setSlackFactor(slack);
		}
	}

	// public void addParallelGroup(ScheduleScheme scheme, String partTaskUid,
	// List<SOperationTask> opList) throws Exception {
	//
	// SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
	// if (partTask == null)
	// return;
	//
	// for (SOperationTask so : opList) {
	// SParallelGroup sg = new SParallelGroup();
	// sg.setParentTask(partTask);
	// sg.setParentTaskUid(partTaskUid);
	// sg
	// .setTaskScheduleType(SOperationTask.TASKSCHEDULETYPE_PARALLELGROUP);
	// sg.setOperationIdDesc(so.getOperationIdDesc());
	// sg.setOutlineNumber(so.getOutlineNumber());
	// sg.setTaskName(so.getTaskName());
	// sg.setTaskUid(IdentityGenerator.GetIdentityString());
	// partTask.getOperationTaskList().add(sg);
	// scheme.getAllOperationTaskMap().put(sg.getTaskUid(), sg);
	// }
	// }

	public void saveOperationTask(ScheduleScheme scheme, String partTaskUid,
			List<SOperationTask> opList, boolean modifyLink) throws Exception {
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
		if (partTask == null)
			throw new Exception("找不到该任务号对应的零件任务：" + partTaskUid);
		float iOperationId = 0;
		for (SOperationTask so : opList) {
			if (so.getObjectState() == BasicModel.OBJECTSTATE_TOBEDELETED) {
				removeOperationTask(scheme, so.getTaskUid());

				// 写日志
				Element taskElement = new Element("OPERATIONTASK_DELETE");
				// taskElement.setAttribute("taskUid",
				// operationTask.getTaskUid());
				taskElement.setAttribute("partUid", so.getPartUid());
				taskElement.setAttribute("drawingId", so.getDrawingId());
				// taskElement.setAttribute("partName", so.getPartName());
				if ("".equals(so.getBatchNum())) {
					taskElement.setAttribute("batchNum", so.getParentTask()
							.getBatchNum());
				} else {
					taskElement.setAttribute("batchNum", so.getBatchNum());
				}

				taskElement.setAttribute("operationIdDesc", so
						.getOperationIdDesc());
				taskElement.setAttribute("taskName", so.getTaskName());
				taskElement.setAttribute("operationId", String.valueOf(so
						.getOperationId()));
				if (so.getPartName() != null) {
					taskElement.setAttribute("partName", so.getPartName());
				} else {
					taskElement.setAttribute("partName", "");
				}

				taskElement.setAttribute("planQty", String.valueOf(so
						.getPlanQty()));
				taskElement.setAttribute("completeQty", String.valueOf(so
						.getCompleteQty()));
				taskElement.setAttribute("estiRunTime", String.valueOf(so
						.getEstiRunTime()));
				taskElement.setAttribute("estiPreTime", String.valueOf(so
						.getEstiPreTime()));
				taskElement.setAttribute("estiDelayTime", String.valueOf(so
						.getEstiDelayTime()));
				if (so.getSuccOperationStr() != null) {
					taskElement.setAttribute("succOperationStr", so
							.getSuccOperationStr());
				} else {
					taskElement.setAttribute("succOperationStr", "");
				}

				if (so.getMasterShop() != null) {
					taskElement.setAttribute("masterShop", so.getMasterShop());
				} else {
					taskElement.setAttribute("masterShop", "");
				}

				if (so.getMasterShopName() != null) {
					taskElement.setAttribute("masterShopName", so
							.getMasterShopName());
				} else {
					taskElement.setAttribute("masterShopName", "");
				}

				if (so.getDeviceClass() != null) {
					taskElement
							.setAttribute("deviceClass", so.getDeviceClass());
				} else {
					taskElement.setAttribute("deviceClass", "");
				}
				if (so.getDeviceClassName() != null) {
					taskElement.setAttribute("deviceClassName", so
							.getDeviceClassName());
				} else {
					taskElement.setAttribute("deviceClassName", "");
				}

				if (so.getDevice() != null
						&& so.getDevice().getDeviceName() != null) {
					taskElement.setAttribute("deviceName", so.getDevice()
							.getDeviceName());
				} else {
					taskElement.setAttribute("deviceName", "");
				}
				if (so.getDeviceUid() != null) {
					taskElement.setAttribute("deviceUid", so.getDeviceUid());
				} else {
					taskElement.setAttribute("deviceUid", "");
				}

				if (so.getEarlyStart() != null) {
					taskElement.setAttribute("earlyStart", String.valueOf(so
							.getEarlyStart()));
				} else {
					taskElement.setAttribute("earlyStart", "");
				}
				if (so.getLateFinish() != null) {
					taskElement.setAttribute("lateFinish", String.valueOf(so
							.getLateFinish()));
				} else {
					taskElement.setAttribute("lateFinish", "");
				}

				if (so.getDeviceSeq() != null) {
					taskElement.setAttribute("deviceSeq", String.valueOf(so
							.getDeviceSeq()));
				} else {
					taskElement.setAttribute("deviceSeq", "");
				}
				if (so.getLocked() != null) {
					taskElement.setAttribute("locked", String.valueOf(so
							.getLocked()));
				} else {
					taskElement.setAttribute("locked", "");
				}

				this.scheduleOperationRecordManager.writeOperOperationLog(
						scheme, so, so,
						ScheduleEvent.EVENTTYPE_OPERATIONTASK_DELETE);

				this.scheduleEventManager.writeOperLog(scheme,
						ScheduleEvent.EVENTTYPE_OPERATIONTASK_DELETE,
						taskElement);
			} else {

				if (so.getObjectState() == BasicModel.OBJECTSTATE_TOBEADDED) {
					addOperationTask(scheme, so, partTask);
					// 写日志
					Element taskElement = new Element("OPERATIONTASK_ADD");
					if (so.getTaskUid() != null) {
						taskElement.setAttribute("taskUid", so.getTaskUid());
					} else {
						taskElement.setAttribute("taskUid", "");
					}
					if (so.getPartUid() != null) {
						taskElement.setAttribute("partUid", so.getPartUid());
					} else {
						taskElement.setAttribute("partUid", "");
					}
					if (so.getDrawingId() != null) {
						taskElement
								.setAttribute("drawingId", so.getDrawingId());
					} else {
						taskElement.setAttribute("drawingId", "");
					}

					// taskElement.setAttribute("partName", so.getPartName());
					if (so.getBatchNum() != null) {
						taskElement.setAttribute("batchNum", so.getBatchNum());
					} else {
						taskElement.setAttribute("batchNum", "");
					}
					if (so.getOperationIdDesc() != null) {
						taskElement.setAttribute("operationIdDesc", so
								.getOperationIdDesc());
					} else {
						taskElement.setAttribute("operationIdDesc", "");
					}
					if (so.getTaskName() != null) {
						taskElement.setAttribute("taskName", so.getTaskName());
					} else {
						taskElement.setAttribute("taskName", "");
					}

					if (so.getLocked() != null) {
						taskElement.setAttribute("locked", String.valueOf(so
								.getLocked()));
					}
					if (so.getSuccOperationStr() != null) {
						taskElement.setAttribute("succOperationStr", so
								.getSuccOperationStr());
					} else {
						taskElement.setAttribute("succOperationStr", "");
					}
					taskElement.setAttribute("operationId", String.valueOf(so
							.getOperationId()));
					SimpleDateFormat formatDate = new SimpleDateFormat(
							"yyyy-MM-dd HH:mm:ss");
					if (so.getEarlyStart() == null) {
						taskElement.setAttribute("earlyStart", "");
					} else {
						taskElement.setAttribute("earlyStart", formatDate
								.format(so.getEarlyStart()));
					}
					if (so.getLateFinish() == null) {
						taskElement.setAttribute("lateFinish", "");
					} else {
						taskElement.setAttribute("lateFinish", formatDate
								.format(so.getLateFinish()));
					}
					taskElement.setAttribute("planQty", String.valueOf(so
							.getPlanQty()));
					taskElement.setAttribute("completeQty", String.valueOf(so
							.getCompleteQty()));
					taskElement.setAttribute("estiRunTime", String.valueOf(so
							.getEstiRunTime()));
					taskElement.setAttribute("estiPreTime", String.valueOf(so
							.getEstiPreTime()));

					this.scheduleOperationRecordManager.writeOperOperationLog(
							scheme, so, so,
							ScheduleEvent.EVENTTYPE_OPERATIONTASK_ADD);

					this.scheduleEventManager.writeOperLog(scheme,
							ScheduleEvent.EVENTTYPE_OPERATIONTASK_ADD,
							taskElement);

				} else if (so.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
					SOperationTask oldOperationTask = scheme
							.getAllOperationTaskMap().get(so.getTaskUid());
					if (oldOperationTask == null)
						throw new Exception("找不到更新的工序任务！" + so);

					// 写日志
					// 旧的信息
					Element taskElement = new Element("OPERATIONTASK_PLANINFO");
					taskElement.setAttribute("partUid", oldOperationTask
							.getPartUid());
					taskElement.setAttribute("taskUid", oldOperationTask
							.getTaskUid());
					taskElement.setAttribute("drawingId", oldOperationTask
							.getDrawingId());
					if (oldOperationTask.getPartName() != null) {
						taskElement.setAttribute("partName", oldOperationTask
								.getPartName());
					} else {
						taskElement.setAttribute("partName", "");
					}
					// taskElement.setAttribute("partName", so.getPartName());
					taskElement.setAttribute("batchNum", oldOperationTask
							.getBatchNum());
					taskElement.setAttribute("operationIdDesc",
							oldOperationTask.getOperationIdDesc());
					if (oldOperationTask.getOperationId() != null) {
						taskElement.setAttribute("operationId", String
								.valueOf(oldOperationTask.getOperationId()));
					} else {
						taskElement.setAttribute("operationId", "");
					}
					taskElement.setAttribute("operationIdDesc",
							oldOperationTask.getOperationIdDesc());
					taskElement.setAttribute("taskName", oldOperationTask
							.getTaskName());
					if (oldOperationTask.getLocked() != null) {
						taskElement.setAttribute("locked", String
								.valueOf(oldOperationTask.getLocked()));
					}

					if (oldOperationTask.getSuccOperationStr() != null) {
						taskElement.setAttribute("succOperationStr",
								oldOperationTask.getSuccOperationStr());
					} else {
						taskElement.setAttribute("succOperationStr", "");
					}

					SimpleDateFormat formatDate = new SimpleDateFormat(
							"yyyy-MM-dd HH:mm:ss");
					if (oldOperationTask.getEarlyStart() == null) {
						taskElement.setAttribute("earlyStart", "");
					} else {
						taskElement.setAttribute("earlyStart", formatDate
								.format(oldOperationTask.getEarlyStart()));
					}
					if (oldOperationTask.getLateFinish() == null) {
						taskElement.setAttribute("lateFinish", "");
					} else {
						taskElement.setAttribute("lateFinish", formatDate
								.format(oldOperationTask.getLateFinish()));
					}
					taskElement.setAttribute("planQty", String
							.valueOf(oldOperationTask.getPlanQty()));
					taskElement.setAttribute("completeQty", String
							.valueOf(oldOperationTask.getCompleteQty()));
					taskElement.setAttribute("estiRunTime", String
							.valueOf(oldOperationTask.getEstiRunTime()));
					taskElement.setAttribute("estiPreTime", String
							.valueOf(oldOperationTask.getEstiPreTime()));
					taskElement.setAttribute("estiDelayTime", String
							.valueOf(oldOperationTask.getEstiDelayTime()));

					if (oldOperationTask.getDevice() != null) {
						taskElement.setAttribute("deviceUid", oldOperationTask
								.getDeviceUid());
						taskElement.setAttribute("deviceName", oldOperationTask
								.getDevice().getDeviceName());
					} else {
						taskElement.setAttribute("deviceUid", "");
						taskElement.setAttribute("deviceName", "");
					}
					if (oldOperationTask.getDeviceSeq() != null) {
						taskElement.setAttribute("deviceSeq", String
								.valueOf(oldOperationTask.getDeviceSeq()));
					} else {
						taskElement.setAttribute("deviceSeq", "");
					}

					if (oldOperationTask.getMasterShop() != null) {
						taskElement.setAttribute("masterShop", oldOperationTask
								.getMasterShop());
					} else {
						taskElement.setAttribute("masterShop", "");
					}

					if (oldOperationTask.getMasterShopName() != null) {
						taskElement.setAttribute("masterShopName",
								oldOperationTask.getMasterShopName());
					} else {
						taskElement.setAttribute("masterShopName", "");
					}

					if (oldOperationTask.getDeviceClass() != null) {
						taskElement.setAttribute("deviceClass",
								oldOperationTask.getDeviceClass());
					} else {
						taskElement.setAttribute("deviceClass", "");
					}
					if (oldOperationTask.getDeviceClassName() != null) {
						taskElement.setAttribute("deviceClassName",
								oldOperationTask.getDeviceClassName());
					} else {
						taskElement.setAttribute("deviceClassName", "");
					}

					updateOperationTask(scheme, so);

					// 新的信息
					Element newTaskElement = new Element("newPlanInfo");
					newTaskElement.setAttribute("partUid", so.getPartUid());
					newTaskElement.setAttribute("taskUid", so.getTaskUid());
					newTaskElement.setAttribute("drawingId", so.getDrawingId());
					if (so.getPartName() != null) {
						newTaskElement.setAttribute("partName", so
								.getPartName());
					} else {
						newTaskElement.setAttribute("partName", "");
					}
					newTaskElement.setAttribute("batchNum", so.getBatchNum());
					newTaskElement.setAttribute("operationIdDesc", so
							.getOperationIdDesc());
					if (so.getOperationId() != null) {
						newTaskElement.setAttribute("operationId", String
								.valueOf(so.getOperationId()));
					} else {
						newTaskElement.setAttribute("operationId", "");
					}
					newTaskElement.setAttribute("taskName", so.getTaskName());
					if (so.getLocked() != null) {
						newTaskElement.setAttribute("locked", String.valueOf(so
								.getLocked()));
					} else {
						newTaskElement.setAttribute("locked", "");
					}

					if (so.getSuccOperationStr() != null) {
						newTaskElement.setAttribute("succOperationStr", so
								.getSuccOperationStr());
					} else {
						newTaskElement.setAttribute("succOperationStr", "");
					}
					if (so.getEarlyStart() == null) {
						newTaskElement.setAttribute("earlyStart", "");
					} else {
						newTaskElement.setAttribute("earlyStart", formatDate
								.format(so.getEarlyStart()));
					}
					if (so.getLateFinish() == null) {
						newTaskElement.setAttribute("lateFinish", "");
					} else {
						newTaskElement.setAttribute("lateFinish", formatDate
								.format(so.getLateFinish()));
					}
					newTaskElement.setAttribute("planQty", String.valueOf(so
							.getPlanQty()));
					newTaskElement.setAttribute("completeQty", String
							.valueOf(so.getCompleteQty()));
					newTaskElement.setAttribute("estiRunTime", String
							.valueOf(so.getEstiRunTime()));
					newTaskElement.setAttribute("estiPreTime", String
							.valueOf(so.getEstiPreTime()));
					newTaskElement.setAttribute("estiDelayTime", String
							.valueOf(so.getEstiDelayTime()));
					if (oldOperationTask.getDevice() != null) {
						newTaskElement.setAttribute("deviceUid", so
								.getDeviceUid());
						newTaskElement.setAttribute("deviceName", so
								.getDevice().getDeviceName());
					} else {
						newTaskElement.setAttribute("deviceUid", "");
						newTaskElement.setAttribute("deviceName", "");
					}
					if (so.getDeviceSeq() != null) {
						newTaskElement.setAttribute("deviceSeq", String
								.valueOf(so.getDeviceSeq()));
					} else {
						newTaskElement.setAttribute("deviceSeq", "");
					}
					if (so.getMasterShop() != null) {
						newTaskElement.setAttribute("masterShop", so
								.getMasterShop());
					} else {
						newTaskElement.setAttribute("masterShop", "");
					}

					if (so.getMasterShopName() != null) {
						newTaskElement.setAttribute("masterShopName", so
								.getMasterShopName());
					} else {
						newTaskElement.setAttribute("masterShopName", "");
					}

					if (so.getDeviceClass() != null) {
						newTaskElement.setAttribute("deviceClass", so
								.getDeviceClass());
					} else {
						newTaskElement.setAttribute("deviceClass", "");
					}
					if (so.getDeviceClassName() != null) {
						newTaskElement.setAttribute("deviceClassName", so
								.getDeviceClassName());
					} else {
						newTaskElement.setAttribute("deviceClassName", "");
					}

					taskElement.addContent(newTaskElement);

					this.scheduleOperationRecordManager.writeOperOperationLog(
							scheme, oldOperationTask, so,
							ScheduleEvent.EVENTTYPE_OPERATIONTASK_PLANINFO);
					this.scheduleEventManager.writeOperLog(scheme,
							ScheduleEvent.EVENTTYPE_OPERATIONTASK_PLANINFO,
							taskElement);
				}

				if (modifyLink) {
					SOperationTask so1 = scheme.getAllOperationTaskMap().get(
							so.getTaskUid());
					if (so1 != null) {
						// so.setOperationId(++iOperationId);
						so1.setSuccOperationStr(so.getSuccOperationStr());
					}
				}

			}

		}

		if (modifyLink && partTask.getOperationTaskList().size() > 0) {
			// // 先将所有链接删除
			// 但这样删除会去掉一些用户定义的链接信息
			//
			// for (SOperationTask so : partTask.getOperationTaskList()) {
			// scheduleLinkManager.deleteSuccLink(so);
			//
			// }
			// 再彻底重建

			for (SOperationTask so : partTask.getOperationTaskList()) {

				String succOperationStr = (so.getSuccOperationStr() == null) ? ""
						: (so.getSuccOperationStr());
				String strOp[] = succOperationStr.split(",");
				Set<SOperationLink> toDeletedSet = new HashSet<SOperationLink>();

				for (SOperationLink slink : so.getSuccLinkSet()) {
					// 必须在同一个零件任务之内
					// 排除虚拟链接
					// lqm todo
					// 20130806
					// 以后可能需要支持多种链接，比如工序与零件任务之间的链接
					String sp = slink.getSuccOperationTask().getParentTaskUid();
					if (!(sp != null && !slink.getVirtualLink()
							&& partTaskUid != null && sp.equals(partTaskUid)))
						continue;

					boolean exists = false;
					for (int i = 0; i < strOp.length; i++) {
						if (!strOp[i].equals("")
								&& strOp[i].equals(slink.getSuccOperationTask()
										.getOperationIdDesc())) {
							exists = true;
							strOp[i] = "";// 这样实现在下面的循环中不添加
							break;
						}
					}
					// 如果在新的字符串中没有则移除
					if (!exists)
						toDeletedSet.add(slink);

				}
				for (SOperationLink slink : toDeletedSet) {
					scheduleLinkManager.deleteLink(slink);
				}

				for (int i = 0; i < strOp.length; i++) {
					if (!strOp[i].equals("")) {
						SOperationTask succSo = partTask.getByIddesc(strOp[i]);
						if (succSo != null)
							scheduleLinkManager.addLink(so, succSo, 1, 0);
					}
				}
			}

			// 判断是否出现循环链接

			// boolean allCycle = true; // 判断所有任务都没有前置工序链接
			for (SOperationTask so : partTask.getOperationTaskList()) {

				// 这个条件种判断方法会导致本来就形成环路的链接不需进行验证
				// 但如果每道工序均验证效率又偏低
				// todo,以后有时间再改进
				// if (so.getPredLinkSet() == null
				// || so.getPredLinkSet().size() == 0) {
				// allCycle = false;
				cycleLinkCheck(so, so, false);
				// }
			}
			// if (allCycle) {
			// throw new Exception("警告：工序任务出现循环链接，请仔细检查！");
			// }

			// 更新工序任务工序距离
			this.calTaskDistance(partTask);

		}

	}

	 
	public void updateScheduleLink(boolean modifyLink, SOperationTask newOp,
			SPartTask partTask) throws Exception {
		if (modifyLink && partTask.getOperationTaskList().size() > 0) {
			// // 先将所有链接删除
			// 但这样删除会去掉一些用户定义的链接信息
			//
			// for (SOperationTask so : partTask.getOperationTaskList()) {
			// scheduleLinkManager.deleteSuccLink(so);
			//
			// }
			// 再彻底重建

			for (SOperationTask so : partTask.getOperationTaskList()) {

				String succOperationStr = (so.getSuccOperationStr() == null) ? ""
						: (so.getSuccOperationStr());
				String strOp[] = succOperationStr.split(",");
				Set<SOperationLink> toDeletedSet = new HashSet<SOperationLink>();

				for (SOperationLink slink : so.getSuccLinkSet()) {
					// 必须在同一个零件任务之内
					// 排除虚拟链接
					// lqm todo
					// 20130806
					// 以后可能需要支持多种链接，比如工序与零件任务之间的链接
					String sp = slink.getSuccOperationTask().getParentTaskUid();
					if (!(sp != null && !slink.getVirtualLink()
							&& partTask.getTaskUid() != null && sp
							.equals(partTask.getTaskUid())))
						continue;

					boolean exists = false;
					for (int i = 0; i < strOp.length; i++) {
						if (!strOp[i].equals("")
								&& strOp[i].equals(slink.getSuccOperationTask()
										.getOperationIdDesc())) {
							exists = true;
							strOp[i] = "";// 这样实现在下面的循环中不添加
							break;
						}
					}
					// 如果在新的字符串中没有则移除
					if (!exists)
						toDeletedSet.add(slink);

				}
				for (SOperationLink slink : toDeletedSet) {
					scheduleLinkManager.deleteLink(slink);
				}

				for (int i = 0; i < strOp.length; i++) {
					if (!strOp[i].equals("")) {
						SOperationTask succSo = partTask.getByIddesc(strOp[i]);
						if (succSo != null)
							scheduleLinkManager.addLink(so, succSo, 1, 0);
					}
				}
			}

			// 判断是否出现循环链接

			// boolean allCycle = true; // 判断所有任务都没有前置工序链接
			for (SOperationTask so : partTask.getOperationTaskList()) {

				// 这个条件种判断方法会导致本来就形成环路的链接不需进行验证
				// 但如果每道工序均验证效率又偏低
				// todo,以后有时间再改进
				// if (so.getPredLinkSet() == null
				// || so.getPredLinkSet().size() == 0) {
				// allCycle = false;
				cycleLinkCheck(so, so, false);
				// }
			}
			// if (allCycle) {
			// throw new Exception("警告：工序任务出现循环链接，请仔细检查！");
			// }

			// 更新工序任务工序距离
			this.calTaskDistance(partTask);

		}
	}

	public void refreshOperationDevice(ScheduleScheme scheme, String opUid,
			SOperationTask operationTask) throws Exception {
		// TODO Auto-generated method stub
		if (opUid == null)
			return;
		// 重置operation的设备约束
		List<OperationDevice> operationDeviceList = null;
//		deviceDao
//				.getOperationDeviceContraint(opUid);
		if (scheme.getOperationDeviceMap().containsKey(opUid))
			scheme.getOperationDeviceMap().remove(opUid);

		if (operationDeviceList != null && operationDeviceList.size() > 0)
			scheme.getOperationDeviceMap().put(opUid, operationDeviceList);

		// 重置所有工序任务的设备列表
		if (operationTask == null) {
			for (SOperationTask so : scheme.getAllOperationTaskMap().values()) {
				if (opUid.equals(so.getOpUid())) {
					this.calcAlterResourceList(so);
				}
			}
		} else {
			this.calcAlterResourceList(operationTask);
		}
	}

	public void setDeviceDao(DeviceDao deviceDao) {
		this.deviceDao = deviceDao;
	}

	public void refreshOtherHour(ScheduleScheme scheme, String parentTaskUid)
			throws Exception {
		SPartTask sp = scheme.getAllPartTaskMap().get(parentTaskUid);
		for (SOperationTask fromSo : sp.getOperationTaskList()) {
			for (SOperationTask toSo : scheme.getAllOperationTaskMap().values()) {
				if (toSo.getPartUid().equals(fromSo.getPartUid())
						&& toSo.getOperationIdDesc().equalsIgnoreCase(
								fromSo.getOperationIdDesc())
						&& !(toSo.getTaskUid().equals(fromSo.getTaskUid()))) {
					toSo.setEstiPreTime(fromSo.getEstiPreTime());
					toSo.setEstiRunTime(fromSo.getEstiRunTime());
					toSo.calTaskWork();
				}
			}
		}
	}

	@Transactional
	public void forceAssignToDevice(ScheduleScheme scheme, String taskUid,
			String deviceUid) throws Exception {
		// TODO Auto-generated method stub
		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);

		if (!(operationTask.getDeviceUid() != null && operationTask
				.getDeviceUid().equals(deviceUid))) {

			if (operationTask.isRunning()) {
				String str = "该工序处于已下发状态，请先取消派工后再进行设备变更！\n"
						+ operationTask.toFriendlyString() + "\n";
				if (operationTask.getDevice() != null)
					str += "当前设备为：" + operationTask.getDevice().getDeviceName();
				throw new Exception(str);
			}

			SDevice device = scheme.getDeviceMap().get(deviceUid);
			operationTask.setDevice(device);
			operationTask.setDeviceUid(device.getDeviceUid());

			if (!device.getDeviceClass().equals(operationTask.getDeviceClass())) {
				operationTask.setDeviceClass(device.getDeviceClass());
				operationTask.setDeviceClassName(device.getDeviceClass());
				// 缺省为本部门
				operationTask.setMasterShop(scheme.getDeptUid());
				// 应该用workcenter对象,设置mastershopname
				// todo
				// operationTask.setMasterShopName(scheme.getd)
			}
			// lqm todo
			// 这个应该移除
			// operationTask.getAlterResourceList().clear();
			//
			// ResourceConstraint resourceConstraint = new ResourceConstraint();
			// resourceConstraint.setNeedCapability(1);
			// resourceConstraint.setDevice(device);
			// resourceConstraint.setPriority(1);
			// operationTask.getAlterResourceList().add(resourceConstraint);
			// resourceConstraint = null;
			//
		}
		// 应该增加是否该工序有多个选项的判断
		// lqm todo
		String opUid = operationTask.getOpUid();
//		deviceDao.forceOperationDevice(taskUid, opUid, deviceUid, 1);

		this.refreshOperationDevice(scheme, opUid, operationTask);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.mes.schedule.manager.iface.ScheduleOperationTaskManager#completeTask(com.mes.schedule.persistence.domain.
	 *      ScheduleScheme, com.mes.schedule.persistence.domain.SOperationTask)
	 */
	 
	@Transactional
	public void completeTask(ScheduleScheme scheme, SOperationTask operationTask)
			throws Exception {

		if (operationTask.isFinished())
			return;
		// todo
		// 应该有更加细腻的处理方式
		// 而不是简单的移除
		operationTask.setActualFinish(scheme.getScheduleCurrentTime());
		// 主要是为了显示甘特图
		// todo
		if (operationTask.getPlanFinish() != null
				&& operationTask.getActualFinish().before(
						operationTask.getPlanFinish()))
			operationTask.setPlanFinish(operationTask.getActualFinish());

		operationTask.setTaskState(SOperationTask.TASKSTATE_COMPLETED);
		operationTask.setCompleteQty(operationTask.getPlanQty());

		scheduleLinkManager.deleteSuccLink(operationTask);

		refreshTaskDistance(operationTask);

		// 一旦有工序开始就表明零件任务就开始，但开始时间不一定准确
		SPartTask partTask = operationTask.getParentTask();
		if (partTask != null) {
			// 将该工序任务从零件工序任务列表中移除
			if (partTask.getOperationTaskList() != null
					&& partTask.getOperationTaskList().size() > 0) {
				partTask.getOperationTaskList().remove(operationTask);
			}
			partTask.setTaskState(SPartTask.TASKSTATE_STARTED);
			if (partTask.getActualStart() == null) {
				partTask.setActualStart(scheme.getScheduleCurrentTime());
			}
			schedulePartTaskDao.update(partTask);
		}
		this.update(operationTask);
		// 总开关
		if (scheme.getAllowAutoFinishBeforeTask() != null
				&& scheme.getAllowAutoFinishBeforeTask()) {

			if (partTask != null) {
				// 前置任务递归实现
				Set<SOperationTask> predTasks = this.getAllPredOperationTasks(
						operationTask, partTask);

				for (SOperationTask predTask : predTasks) {
					if (!predTask.isFinished())
						this.completeTask(scheme, predTask);
				}
			}
		}
		this.update(operationTask);
		// this.removeOperationTask(operationTask);
		if (partTask != null) {
			boolean isFinish = true;
			List<SOperationTask> operationTaskList = partTask
					.getOperationTaskList();
			for (int j = operationTaskList.size() - 1; j >= 0; j--) {
				SOperationTask so = operationTaskList.get(j);
				if (so.getTaskState() < SOperationTask.TASKSTATE_COMPLETED) {
					isFinish = false;
					break;
				}
			}

			if (isFinish) {
				SchedulePartTaskManager scp = SpringUtils
						.getBean("schedulePartTaskManager");
				// 防止找不到方案，先判断一下 added by ha
				if (partTask.getScheme() == null) {
					partTask.setScheme(scheme);
				}
				if (partTask.getTaskState() < SPartTask.TASKSTATE_COMPLETED) {
					scp.completePartTask(partTask);
				}

			} else {
				// 如果下一道工序是协作，而且满足部门条件，则自动发布到协作车间
				SOperationTask nextOperationTask = null;
				for (int j = 0; j < operationTaskList.size(); j++) {
					SOperationTask so = operationTaskList.get(j);
					if (so.getOperationId() >= operationTask.getOperationId()
							&& !so.isFinished()) {
						nextOperationTask = so;
						break;
					}
				}

//				if (nextOperationTask != null) {
//					// 如果是协作工序，而且该部门允许自动发布
//					if ((!nextOperationTask.getMasterShop().equals(
//							scheme.getDeptUid())))
//						if (SysUtil.isDeptExist(nextOperationTask
//								.getMasterShop(),
//								"schedule.autoPublishCoTaskDept"))
//							this.publishCoTask(nextOperationTask
//									.getScheduleUid(), nextOperationTask
//									.getTaskUid());
//
//				}

			}

		}

	}

	private void refreshTaskDistance(SOperationTask operationTask)
			throws Exception {
		/*
		 * 设置工序距离
		 */
		if (operationTask.getParentTask() != null) {
			// 避免循环注入
			SchedulePartTaskManager schedulePartTaskManager = (SchedulePartTaskManager) SpringUtils
					.getBean("schedulePartTaskManager");
			schedulePartTaskManager.refreshTaskDistance(operationTask
					.getParentTask());
		}
	}

	 
	public void completePrepare(ScheduleScheme scheme,
			SOperationTask operationTask, String deviceUid, Date actualFinish)
			throws Exception {
		// TODO Auto-generated method stub
		operationTask.setActualPrepareFinish(actualFinish);
		operationTask.setTaskState(2071);
		operationTask.calTaskWork();
		// todo
		// 应该有prepareReady状态位
	}

	@Transactional
	 
	public void startTask(ScheduleScheme scheme, SOperationTask operationTask,
			String deviceUid, Date actualStart) throws Exception {
		// TODO Auto-generated method stub
		// todo
		// 开始时间是否需要这么快就滚动？
		// 开始时间是否应该已经开始了就不让变动
		if (actualStart == null)
			actualStart = scheme.getScheduleCurrentTime();
		operationTask.setTaskState(207);
		if (operationTask.getActualStart() == null)
			operationTask.setActualStart(actualStart);

		SPartTask partTask = operationTask.getParentTask();
		// 零件任务如果未开始并且没有实际开始时间，就需要设置零件的实际开始 added by hba
		if (partTask != null) {
			if (partTask.getTaskState() < SPartTask.TASKSTATE_STARTED) {
				partTask.setTaskState(SPartTask.TASKSTATE_STARTED);
				if (partTask.getActualStart() == null) {
					partTask.setActualStart(actualStart);
				}
				schedulePartTaskDao.update(partTask);
			}
		}
		// hba

		operationTask.setEarlyStart(null);

		this.scheduleLinkManager.deletePredLink(operationTask);

		// if (deviceUid != null)
		// lockStartedTask(operationTask, deviceUid);
		// 将同设备其它任务设置为暂停
	}

	private void changeDevice(SOperationTask operationTask, String deviceUid) {
		if (operationTask.getDeviceUid() != null && deviceUid != null
				&& !operationTask.getDeviceUid().equals(deviceUid)) {
			// 变一台设备没这么简单啊
			// TODO
			// 工作中心变了怎么办，部门变了怎么办
			SDevice device = operationTask.getScheme().getDeviceMap().get(
					deviceUid);
			if (device != null) {
				operationTask.setDevice(device);

				operationTask.setDeviceUid(deviceUid);
			}
		}
	}

	// private void lockStartedTask(SOperationTask operationTask, String
	// deviceUid) {
	//
	// //changeDevice(operationTask, deviceUid);
	// // by lqm
	// // 已开始的任务没必要锁定，让他拥有最高优先级
	// // operationTask.setLocked(1);
	// operationTask.setEarlyStart(null);
	// // operationTask.setTaskDistance(0);
	// // operationTask.getPredLinkSet().clear();
	// }

	 
	public void feedbackTask(ScheduleScheme scheme,
			SOperationTask operationTask, Double completeQty, String deviceUid,
			Date workDate) throws Exception {
		if (completeQty == null || completeQty == 0)
			return;

		// todo
		// 应该放在operationTaskManager中
		// 取消2073状态，这个状态意义不大
		// operationTask.setTaskState(2073);
		operationTask.setCompleteQty(operationTask.getCompleteQty()
				+ completeQty);
		if (operationTask.getCompleteQty() < 0)
			operationTask.setCompleteQty(0d);
		if (operationTask.getCompleteQty() >= operationTask.getPlanQty()) {
			operationTask.setCompleteQty(operationTask.getPlanQty());
			// completeTask应该允许传入workdate参数
			// todo
			this.completeTask(scheme, operationTask);

			return;

		}

		// 在反馈最后一道工序时需要更新零件的完成数 added by hba
		SPartTask partTask = operationTask.getParentTask();
		SOperationTask lastOperationTask = new SOperationTask();
		if (partTask != null) {
			// 只要有反馈数量就将任务开始
			if (operationTask.getCompleteQty() > 0
					&& partTask.getTaskState() < SPartTask.TASKSTATE_STARTED) {
				partTask.setTaskState(SPartTask.TASKSTATE_STARTED);
				if (partTask.getActualStart() == null) {
					partTask.setActualStart(scheme.getScheduleCurrentTime());
				}
				schedulePartTaskDao.update(partTask);
			}
			if (partTask.getOperationTaskList() != null
					&& partTask.getOperationTaskList().size() > 0) {
				// 获取最后一道工序
				lastOperationTask = partTask.getOperationTaskList().get(
						partTask.getOperationTaskList().size() - 1);
				if (operationTask.equals(lastOperationTask)) {
					partTask.setCompleteQty(operationTask.getCompleteQty());
					schedulePartTaskDao.update(partTask);
				}
			}
		}
		// hba

		// 减少无谓的调整
		// lqm todo
		// 应该参数化，由工段长自己选择
		// this.changeDevice(operationTask, deviceUid);

		// 万一有负数的反馈怎么办？
		// todo
		// 允许自动回归加工时间
		if (scheme.getAllowAutoRegressHour() != null
				&& scheme.getAllowAutoRegressHour()
				&& operationTask.getDevice() != null) {

			if (operationTask.getCompleteQty() > 1 && workDate != null) {
				if (operationTask.getActualFirstFinish() != null
						&& operationTask.getActualFirstFinish()
								.before(workDate))// 如果存在首件三检
				{

					// 相差的分钟数
					// todo
					// 应该是该设备考虑日历，中断之后的时间
					// double totalrunTime= (workDate.getTime() - operationTask
					// .getActualFirstFinish().getTime()) / (60000);

					double totalrunTime = this.scheduleDeviceManager
							.getAvailableSegementCount(operationTask
									.getDevice(), operationTask
									.getActualFirstFinish(), workDate)
							* scheme.getScheduleInterval();

					// todo
					// 首件可能是多个零件
					double runtime = totalrunTime
							/ (operationTask.getCompleteQty() - 1);

					// todo
					// 应该是保留多种运行时间
					operationTask.setEstiRunTime(runtime);

				} else if (operationTask.getActualStart() != null
						&& operationTask.getActualStart().before(workDate))// 如果存在首件三检
				{

					// 相差的分钟数
					// todo
					// 应该是考虑日历，中断之后的时间
					// double totalrunTime = (workDate.getTime() - operationTask
					// .getActualStart().getTime()) / (60000);
					double totalrunTime = this.scheduleDeviceManager
							.getAvailableSegementCount(operationTask
									.getDevice(), operationTask
									.getActualStart(), workDate)
							* scheme.getScheduleInterval();

					// todo
					// 首件可能是多个零件
					double runtime = 0;

					// todo
					// 应该是保留多种运行时间
					if (totalrunTime > operationTask.getEstiPreTime()) {
						runtime = (totalrunTime - operationTask
								.getEstiPreTime())
								/ (operationTask.getCompleteQty());
					} else
						runtime = (totalrunTime)
								/ (operationTask.getCompleteQty());
					operationTask.setEstiRunTime(runtime);

				}
			}
		}

		// 重新计算剩余工时
		operationTask.calTaskWork();

		// 更新工序任务
		this.update(operationTask);

	}

	 
	public void completeFirstCheck(ScheduleScheme scheme,
			SOperationTask operationTask, String deviceUid, Date actualFinish)
			throws Exception {
		operationTask.setTaskState(2072);
		operationTask.setActualFirstFinish(actualFinish);

	}

	/*
	 * 
	 * (non-Javadoc)
	 * 
	 * @see com.mes.schedule.manager.iface.ScheduleOperationTaskManager#replaceWorkCenter(com.mes.schedule.persistence.domain
	 *      .ScheduleScheme, com.mes.schedule.persistence.domain.SOperationTask,
	 *      java.lang.String, java.lang.String)
	 */
	 
	public void replaceWorkCenter(ScheduleScheme scheme,
			SOperationTask operationTask, String workCenterUid,
			String workCenterName) throws Exception {
		// TODO Auto-generated method stub
		operationTask.setDeviceClass(workCenterUid);
		operationTask.setDeviceClassName(workCenterName);
		this.calcAlterResourceList(operationTask);
		// 重新设置部门
		// this.setTaskMasterShop(operationTask);

	}

	 
	public void updateRejectQty(ScheduleScheme scheme,
			SOperationTask operationTask, double rejectQty) throws Exception {
		// TODO Auto-generated method stub
		log.debug("开始更新报废数量" + operationTask + ",报废数量为" + rejectQty);
		SPartTask schedulePartTask = operationTask.getParentTask();
		if (schedulePartTask != null) {
			for (SOperationTask so : schedulePartTask.getOperationTaskList()) {
				so.setPlanQty(so.getPlanQty() - rejectQty);
			}
			schedulePartTask.setPlanQty(schedulePartTask.getPlanQty()
					- rejectQty);
		} else {
			operationTask.setPlanQty(operationTask.getPlanQty() - rejectQty);
		}

	}

	 
	public int calAssnPriority(SOperationTask operationTask, String deviceUid) {
		// int assnPriority = 5;
		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals(
					"f6d1bc59-4794-466b-adc6-9dc0cba2acf5")) {
				log.debug("aa");
			}
		}

		// if (operationTask.getAlterResourceList() != null
		// && operationTask.getAlterResourceList().size() > 0) {
		// for (ResourceConstraint resourceConstraint : (operationTask
		// .getAlterResourceList())) {
		// if (deviceUid.equals(resourceConstraint.getDeviceUid())) {
		// if (resourceConstraint.getPriority() < assnPriority)
		// assnPriority = (int) resourceConstraint.getPriority();
		// }
		// }
		// }
		if (operationTask.getAlterResourceMap().containsKey(deviceUid)) {
			// 如果只有一条资源，缺省显示为必须分派到此设备
			if (operationTask.getAlterResourceMap().size() == 1)
				return 1;

			Integer p = operationTask.getAlterResourceMap().get(deviceUid)
					.getPriority();
			if (p != null)
				return p;
		}

		// todo
		// 应该用常量
		return 5;

	}

	@Transactional
	 
	public void forceNotAssignToDevice(ScheduleScheme scheme, String taskUid,
			String deviceUid) throws Exception {
		// TODO Auto-generated method stub
		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);

		if (!this.canChangeDevice(operationTask))
			throw new Exception("该任务不能从本设备上移除，请检查该任务是否已派工、已锁定或存在设备序列！");

		if (operationTask.getDeviceSeq() != null)
			operationTask.setDeviceSeq(null);
		if (operationTask.getDeviceUid() != null
				&& operationTask.getDeviceUid().equals(deviceUid)) {
			operationTask.setDevice(null);
			operationTask.setDeviceUid(null);
		}

		// 先重新计算一下，防止强制设置设备时清空它
		// this.calcAlterResourceList(operationTask);
		// List<ResourceConstraint> resourceConstraintList = operationTask
		// .getAlterResourceList();
		//
		// if (resourceConstraintList != null && resourceConstraintList.size() >
		// 0) {
		// for (ResourceConstraint resourceConstraint : resourceConstraintList)
		// {
		// if (resourceConstraint.getDeviceUid().equals(deviceUid)) {
		// resourceConstraintList.remove(resourceConstraint);
		// break;
		// }
		//
		// }
		// }

		String opUid = operationTask.getOpUid();
//		deviceDao.forceOperationDevice(taskUid, opUid, deviceUid, 5);

		this.refreshOperationDevice(scheme, opUid, operationTask);

	}

	/**
	 * 计算工序任务的工艺上的最早完成时间 与计算controlEarlyFinish最大的区别是为了在不考虑设备虚拟链接情况下计算工序的等待时间
	 * 主要是为了方便统计工序上的等待时间
	 * 
	 * @param operationTask
	 * @return
	 */
	public Date getRealControlEarlyFinish(SOperationTask operationTask) {

		ScheduleScheme scheme = operationTask.getScheme();
		// 对当前时间的限制 //限制最早开始时间
		operationTask.setControlEarlyFinish(scheme.getScheduleCurrentTime());
		long controlEarlyFinish = scheme.getScheduleCurrentTime().getTime();

		Set<SOperationLink> operationLinkSet = operationTask.getPredLinkSet();
		if (operationLinkSet != null && operationLinkSet.size() > 0) {
			for (SOperationLink predLink : operationTask.getPredLinkSet()) {
				// 与计算controlStart最大的不同
				if (predLink.getVirtualLink())
					continue;
				SOperationTask predTask = predLink.getPredOperationTask();

				if (predTask.isFinished())
					continue;

				// 存在误差 todo
				// if(log.isDebugEnabled())
				// {
				if (predTask.getPlanFinish() == null) {
					log.error("调度时发现前置任务计划结束时间为空," + predTask);
					return null;
				}
				// }
				long temp;

				// 用clone防止更新
				SOperationLink link = null;

				try {
					link = (SOperationLink) predLink.clone();
				} catch (CloneNotSupportedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				this.decideFlowMode(link);

				if (link.getLinkLag() == null)
					link.setLinkLag(0);
				if (link.getMoveType() == null)
					link.setMoveType(SOperationLink.MOVETYPE_SEQUENCE);
				int transferQty = (link.getTransferQty() == null) ? 1 : link
						.getTransferQty();
				switch (link.getMoveType()) {
				case SOperationLink.MOVETYPE_SEQUENCE: {
					temp = predTask.getPlanFinish().getTime()
							+ ((long) ((operationTask.getPlanQty() - operationTask
									.getCompleteQty()) * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}
				case SOperationLink.MOVETYPE_FLOW: {
					// 暂时流水加工也采用这种计算

					temp = predTask.getPlanFinish().getTime()
							+ ((long) (transferQty * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}
				case SOperationLink.MOVETYPE_FLOWSEQUENCE: {

					temp = predTask.getPlanFinish().getTime()
							+ ((long) (transferQty * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}

				default: {
					// 缺省为顺序加工
					temp = predTask.getPlanFinish().getTime()
							+ ((long) ((operationTask.getPlanQty() - operationTask
									.getCompleteQty()) * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}
				}

				if (controlEarlyFinish < temp) {
					controlEarlyFinish = temp;
				}
			}

			return new Date(controlEarlyFinish);
		}

		return null;

	}

	/**
	 * 计算工序的最早完成时间 调度计算时要保证完成时间大于此时间
	 */
	 
	public void calcControlEarlyFinish(SOperationTask operationTask) {
		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals(
					"78c2ae30-2b49-43f3-b0d0-5cbfe64c926e")) {
				log.debug(operationTask);
			}
		}
		ScheduleScheme scheme = operationTask.getScheme();
		// 对当前时间的限制 //限制最早开始时间
		operationTask.setControlEarlyFinish(scheme.getScheduleCurrentTime());
		long controlEarlyFinish = scheme.getScheduleCurrentTime().getTime();

		Set<SOperationLink> operationLinkSet = operationTask.getPredLinkSet();
		if (operationLinkSet != null && operationLinkSet.size() > 0) {
			for (SOperationLink link : operationTask.getPredLinkSet()) {
				SOperationTask predTask = link.getPredOperationTask();

				if (predTask.isFinished())
					continue;

				// 由于锁定引起的 前道工序未做完，后道工序开工的现象
				if (predTask.getAssignState() != SOperationTask.ASSNSTATE_SUCCESS
						|| predTask.getPlanStart() == null
						|| predTask.getPlanFinish() == null) {
					// log.debug("前道工序还未排完，可能存在锁定工序先排！"+predTask.getTaskUid());
					return;// 直接返回，因为值已经写入controlStart
				}
				long temp;

				if (link.getLinkLag() == null)
					link.setLinkLag(0);
				if (link.getMoveType() == null)
					link.setMoveType(SOperationLink.MOVETYPE_SEQUENCE);
				int transferQty = (link.getTransferQty() == null) ? 1 : link
						.getTransferQty();
				switch (link.getMoveType()) {
				case SOperationLink.MOVETYPE_SEQUENCE: {
					temp = predTask.getPlanFinish().getTime()
							+ ((long) ((operationTask.getPlanQty() - operationTask
									.getCompleteQty()) * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}
				case SOperationLink.MOVETYPE_FLOW: {
					// 暂时流水加工也采用这种计算
					// 存在误差 todo
					temp = predTask.getPlanFinish().getTime()
							+ ((long) (transferQty * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}
				case SOperationLink.MOVETYPE_FLOWSEQUENCE: {

					temp = predTask.getPlanFinish().getTime()
							+ ((long) (transferQty * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}

				default: {
					// 缺省为顺序加工
					temp = predTask.getPlanFinish().getTime()
							+ ((long) ((operationTask.getPlanQty() - operationTask
									.getCompleteQty()) * operationTask
									.getEstiRunTime())) * 60000;
					break;
				}
				}

				if (controlEarlyFinish < temp) {
					controlEarlyFinish = temp;
				}
			}

			operationTask.setControlEarlyFinish(new Date(controlEarlyFinish));
		}

	}

	public void setScheduleCalendarManager(
			ScheduleCalendarManager scheduleCalendarManager) {
		this.scheduleCalendarManager = scheduleCalendarManager;
	}

	 
	public double calPercentComplete(SOperationTask operationTask) {
		double percentComplete = 0;
		// 计算完成工时
		double totalWork = operationTask.getEstiPreTime()
				+ operationTask.getEstiRunTime() * operationTask.getPlanQty();
		if (operationTask.getCompleteQty() > 0) {
			double completeWork = operationTask.getEstiPreTime()
					+ operationTask.getEstiRunTime()
					* operationTask.getCompleteQty();
			if (totalWork > 0)
				percentComplete = completeWork / totalWork;
		}

		return percentComplete;
	}

	@Transactional
	 
	public void cancelDispatchTask(ScheduleScheme scheme,
			SOperationTask operationTask) throws Exception {

		operationTask.setTaskState(SOperationTask.TASKSTATE_WAITING);
		String creatorUid = "";//SysUtil.getSessionEmployeeId();

		Set<OperationTask> ooSet = this.getOOTasks(operationTask);
		// String[] strBatchNums = operationTask.getBatchNum().split(",");
		// String[] strOperations =
		// operationTask.getOperationIdDesc().split("/");
		// String strOperationIddesc = operationTask.getOperationIdDesc();
		// for (int i = 0; i < strBatchNums.length; i++) {
		// String strBatchNum = strBatchNums[i];

		// for (int j = 0; j < strOperations.length; j++) {
		// String strOperationIddesc = strOperations[j];

		if (ooSet != null && ooSet.size() > 0) {

			for (OperationTask oo : ooSet) {
//				assignmentDeviceManager.cancelTaskAssn(oo.getUuid());

			}
		}

		this.update(operationTask);

		// 取消派工后重新刷新设备的可分配队列
		this.calcAlterResourceList(operationTask);

		controlPrepareTaskInSchedule = this.getControlPrepareTaskInSchedule();
		if (controlPrepareTaskInSchedule) {
			try {
				// 应该只是分拣任务吗？
				// todo
				// this.cancelPrepareTask(operationTask, ooSet);

				// 改成多线程任务
				MtPrepareTaskControl mtPrepareTaskControl = null;
//				new MtPrepareTaskControl(
//						"C", this, operationTask, ooSet, SysUtil
//								.createMMSystemSession());
				SysUtil.getExecutorService().submit((Callable<MtPrepareTaskControl>) mtPrepareTaskControl);

			} catch (Exception e) {
				log.error("取消生产准备任务时发生错误！", e);
			}
		}

	}

	 
	@Transactional
	public void dispatchTask(ScheduleScheme scheme, SOperationTask operationTask)
			throws Exception {

		// if (operationTask instanceof SGroupOperationTask ) {
		// SGroupOperationTask groupTask = (SGroupOperationTask) operationTask;
		// List<SOperationTask> memberTasks = groupTask.getMemberTasks();
		// if (memberTasks != null && memberTasks.size() > 0) {
		// for (SOperationTask memberTask : memberTasks) {
		// this.dispatchTask(scheme, memberTask);
		// }
		// }
		// if (operationTask.getTaskState() <=
		// OperationTask.TASKSTATE_READY)operationTask.setTaskState(SOperationTask.TASKSTATE_DISPATCHED);
		// return;
		// }
		// /*
		// * 支持临时任务派工
		// */
		// if (SOperationTask.TASKTYPE_TEMPTASK
		// .equals(operationTask.getTaskType())) {
		// SOperationTask tempTask = operationTask;
		// OperationTask oo = (OperationTask) this.operationTaskManager
		// .getById(tempTask.getTaskUid());
		// // 创建一个任务
		// if (oo == null) {
		// oo = new OperationTask();
		// oo.setUuid(tempTask.getTaskUid());
		// oo.setPartUid(tempTask.getPartUid());
		// oo.setBatchNum(tempTask.getBatchNum());
		// oo.setOperationIdDesc(tempTask.getOperationIdDesc());
		// oo.setName(tempTask.getTaskName());
		// oo.setTaskState(STempOperationTask.TASKSTATE_READY);
		// oo.setTaskType(tempTask.TASKTYPE_TEMPTASK);
		// oo.setMasterShopUid(scheme.getDeptUid());
		// oo.setDeptUid(scheme.getDeptUid());
		// oo.setPlanQty(Float.valueOf(String.valueOf(tempTask
		// .getPlanQty())));
		// oo.setCreateTime(new Date());
		// this.getOperationTaskManager().add(oo);
		//
		// }
		// // this.dispatchTask(scheme, (STempOperationTask)operationTask);
		// // return;
		// }
		// TODO Auto-generated method stub
		// lqm todo
		// 状态控制很粗糙
		// 添加函数同时用于更新
		// if (operationTask.getTaskState() > 0
		// && operationTask.getTaskState() >=
		// OperationTask.TASKSTATE_DISPATCHED)
		// return;

		String creatorUid = "";//SysUtil.getSessionEmployeeId();
		Set<OperationTask> ooSet = this.getOOTasks(operationTask);
		// String[] strBatchNums = operationTask.getBatchNum().split(",");
		// String[] strOperations =
		// operationTask.getOperationIdDesc().split("/");
		// String strOperationIddesc = operationTask.getOperationIdDesc();
		// for (int i = 0; i < strBatchNums.length; i++) {
		// String strBatchNum = strBatchNums[i];

		// for (int j = 0; j < strOperations.length; j++) {
		// String strOperationIddesc = strOperations[j];
		if (ooSet != null && ooSet.size() > 0) {
			for (OperationTask oo : ooSet) {
				// OperationTask oo = this.operationTaskDao
				// .getOperationTask(operationTask.getPartUid(), strBatchNum,
				// strOperationIddesc);
				// if (oo != null
				// && oo.getTaskState() < OperationTask.TASKSTATE_DISPATCHED) {
				// if (oo != null) {
				try {
//					assignmentDeviceManager.saveOrUpdateAssn(oo.getUuid(),
//							operationTask.getDeviceUid(), null, operationTask
//									.getPlanStart(), operationTask
//									.getPlanFinish(), (double) oo.getPlanQty(),
//							creatorUid);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				// 更新优先级
				oo.setPlanStart(operationTask.getPlanStart());
				oo.setPlanFinish(operationTask.getPlanFinish());
//				oo.setEstiPreOpTime(operationTask.getEstiPreTime());
//				oo.setEstiRunTime(operationTask.getEstiRunTime());
				if (oo.getDevice() != null)// 主要是为了防止 cooperation作为deviceuid
					oo.setDeviceUid(operationTask.getDeviceUid());

//				oo.setSlackFactor(operationTask.getSlackFactor());
				//改变getLocked为getIsLocked，改变setSchedulePriority为setPriority  by lcs
				if (oo.getIsLocked() == null || !oo.getIsLocked())
//					oo.setPriority(operationTask.getPriority().longValue());
				this.operationTaskManager.update(oo);
				// }
			}
		}
		// }
		// 不是很严格的状态控制
		// lqm todo
		if (operationTask.getTaskState() <= OperationTask.TASKSTATE_READY) {
			operationTask.setTaskState(SOperationTask.TASKSTATE_DISPATCHED);
			// operationTask.setTaskState(SOperationTask.TASKSTATE_DISPATCHED);
			try {
				this.update(operationTask);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		// lqmtodo 添加生产准备任务，这里没有完成更新操作
		// 应该参数化这部分
		// 临时判断，不完整
		// by lqm todo

		controlPrepareTaskInSchedule = this.getControlPrepareTaskInSchedule();

		if (controlPrepareTaskInSchedule) {
			if (operationTask.getDevice() != null
					&& operationTask.getDevice().getCriticalLevel() < 6) {
				try {
					// 由于效率问题，改成多线程下达生产准备任务
					// todo
					// 这样就没有多线程控制了
					// saveOrUpdatePrepareTask(operationTask, ooSet);

					// 改成多线程了

					// 生产准备这块效率应该改善，一旦派工产生了太多的单据
					MMSystemSession systemSession = null;
//					SysUtil
//							.createMMSystemSession();
					MtPrepareTaskControl mtPrepareTaskControl = new MtPrepareTaskControl(
							"A", this, operationTask, ooSet, systemSession);
					SysUtil.getExecutorService().submit((Callable<MtPrepareTaskControl>) mtPrepareTaskControl);

				} catch (Exception e) {
					log.error("生成生产准备任务时发生错误！");
					// e.printStackTrace();
				}
			}
		}

	}

	 
	public void interruptTask(ScheduleScheme scheme,
			SOperationTask operationTask, String interruptReason,
			Date interruptDate, Date planRestartDate) throws Exception {
		// TODO Auto-generated method stub
		/*
		 * 缺状态控制
		 */
		operationTask.setTaskState(SOperationTask.TASKSTATE_INTERRUPTED);
		operationTask.setLocked(0);// 不再锁定，让其自然后排

		if (planRestartDate == null) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(scheme.getScheduleCurrentTime());
			calendar.add(Calendar.MINUTE, this.Default_Interrupt_Delay);
			operationTask.setEarlyStart(calendar.getTime());
		}

	}

	 
	public void pauseTask(ScheduleScheme scheme, SOperationTask operationTask,
			String pauseReason, Date pauseDate, Date planResumeDate)
			throws Exception {
		// TODO Auto-generated method stub
		operationTask.setTaskState(SOperationTask.TASKSTATE_PAUSED);
		if (planResumeDate == null) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(scheme.getScheduleCurrentTime());
			calendar.add(Calendar.MINUTE, this.Default_Pause_Delay);
			operationTask.setEarlyStart(calendar.getTime());
		}

	}

	 
	public void restartTask(ScheduleScheme scheme,
			SOperationTask operationTask, String restartReason, Date restartDate)
			throws Exception {
		// TODO Auto-generated method stub
		this.startTask(scheme, operationTask, null, null);

	}

	 
	public void resumeTask(ScheduleScheme scheme, SOperationTask operationTask,
			String resumeReason, Date resumeDate) throws Exception {
		// TODO Auto-generated method stub
		operationTask.setTaskState(SOperationTask.TASKSTATE_STARTED);
		if (operationTask.getPlanStart().after(scheme.getScheduleStart()))
			operationTask.setPlanStart(scheme.getScheduleStart());
		operationTask.setEarlyStart(null);
	}

	@Transactional
	 
	public void changeTaskState(ScheduleScheme scheme,
			SOperationTask operationTask, int taskState, String changeReason,
			Date changeDate) throws Exception {

		// 任务状态改变后，重新设置任务的资源队列
		// lqm todo
		// 应该放在各业务方法中去

		// TODO Auto-generated method stub
		switch (taskState) {
		case 206: {
			this.dispatchTask(scheme, operationTask);
			this.calcAlterResourceList(operationTask);

		}
			break;
		case 2061: {
			this.startOfflinePrepare(scheme, operationTask, null);
			this.calcAlterResourceList(operationTask);

		}
			break;
		case 2069: {
			this.completeOfflinePrepare(scheme, operationTask, null);
			this.calcAlterResourceList(operationTask);
		}
			break;
		case -206: {
			this.cancelDispatchTask(scheme, operationTask);
			this.calcAlterResourceList(operationTask);

		}
			break;
		case 207: {
			this.startTask(scheme, operationTask, null, null);
			this.calcAlterResourceList(operationTask);

		}
			break;
		case 208: {
			this.pauseTask(scheme, operationTask, null, null, null);
			this.calcAlterResourceList(operationTask);

		}
			break;
		case -208: {
			this.resumeTask(scheme, operationTask, changeReason, changeDate);
			this.calcAlterResourceList(operationTask);
		}
			break;
		case 2081: {
			this.interruptTask(scheme, operationTask, null, null, null);
			this.calcAlterResourceList(operationTask);
		}
			break;
		case -2081: {
			this.restartTask(scheme, operationTask, changeReason, changeDate);
			this.calcAlterResourceList(operationTask);
		}
			break;
		case 209: {
			this.completeTask(scheme, operationTask);
			// this.calcAlterResourceList(operationTask);
		}
			break;
		default: {
			operationTask.setTaskState(taskState);
			this.calcAlterResourceList(operationTask);
		}
			break;
		}

		// 直接保存
		this.update(operationTask);

	}

	public AssignmentDeviceManager getAssignmentDeviceManager() {
		return assignmentDeviceManager;
	}

	public void setAssignmentDeviceManager(
			AssignmentDeviceManager assignmentDeviceManager) {
		this.assignmentDeviceManager = assignmentDeviceManager;
	}

	 
	public void mergeTask(List<SOperationTask> subOperationTaskList)
			throws Exception {
		// TODO Auto-generated method stub

	}

	 
	public void splitTask(SOperationTask operationTask, List<Double> part)
			throws Exception {
		// TODO Auto-generated method stub

	}

	 
	public List<SOperationTask> getMemberTaskList(String scheduleUid,
			String groupTaskUid) throws Exception {
		// TODO Auto-generated method stub
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}
		for (SOperationTask operationTask : scheme.getGroupTaskList()) {
			if (groupTaskUid.equals(operationTask.getTaskUid()))
				return ((SGroupOperationTask) operationTask).getMemberTasks();
		}
		return null;

	}

	 
	public void addMemberTask(SGroupOperationTask groupTask, String taskUid)
			throws Exception {
		ScheduleScheme scheme = groupTask.getScheme();
		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);
		if (operationTask == null)
			throw new Exception("找不到对应工序任务：" + taskUid);

		this.addMemberTask(groupTask, operationTask);

	}

	 
	public void deleteMemberTask(SGroupOperationTask groupTask, String taskUid)
			throws Exception {
		ScheduleScheme scheme = groupTask.getScheme();
		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);
		if (operationTask == null)
			throw new Exception("找不到对应工序任务：" + taskUid);
		this.deleteMemberTask(groupTask, operationTask);

	}

	/*
	 * 应该用memberTask,对已经分组的先拆再分 (non-Javadoc)
	 * 
	 * @see com.mes.schedule.manager.iface.ScheduleOperationTaskManager#addMemberTask(com.mes.schedule.persistence.domain
	 *      .SGroupOperationTask,
	 *      com.mes.schedule.persistence.domain.SOperationTask)
	 */
	 
	public void addMemberTask(SGroupOperationTask groupTask,
			SOperationTask memberTask) throws Exception {
		if (groupTask == null)
			throw new Exception("合批任务不能为空！");
		for (SOperationTask mm : groupTask.getMemberTasks()) {
			if (memberTask.equals(mm))
				throw new Exception("任务" + memberTask.toFriendlyString()
						+ "已经属于该工序合批！");
		}
		// 如果属于另外一个分组，则先将其移除
		if (memberTask.getGroupTask() != null) {
			this.deleteMemberTask(memberTask.getGroupTask(), memberTask);
		}
		// 如果本身是一个组集合，先取消再添加，保持组函数的扁平性
		if (memberTask instanceof SGroupOperationTask) {
			List<SOperationTask> mml = new ArrayList<SOperationTask>();
			// 先保存原任务
			for (SOperationTask mm : ((SGroupOperationTask) memberTask)
					.getMemberTasks())
				mml.add(mm);
			// 取消原分组
			this.cancelGroupTask((SGroupOperationTask) memberTask);
			// 再添加
			for (SOperationTask so : mml) {
				addMemberTask(groupTask, so);
			}

		} else {
			memberTask.setGroupTaskUid(groupTask.getTaskUid());
			memberTask.setGroupTask(groupTask);
			groupTask.getMemberTasks().add(memberTask);
			// 移除并非必须选项
			// 因为首道工序如果部分成组会导致某些零件无法排
			// 成组中的任务以后就让它不需移出
			// 出错就让他出错吧
			// try {
			// this.outSchedule(memberTask, false);
			// } catch (Exception e) {
			// // TODO Auto-generated catch block
			// e.printStackTrace();
			// }
		}

	}

	 
	public void deleteMemberTask(SGroupOperationTask groupTask,
			SOperationTask memberTask) throws Exception {
		if (groupTask == null)
			return;

		memberTask.setGroupTask(null);
		memberTask.setGroupTaskUid(null);

		groupTask.getMemberTasks().remove(memberTask);
		// 重新进入调度
		this.intoSchedule(memberTask);

		if (groupTask.getMemberTasks().size() == 0) {
			this.cancelGroupTask(groupTask);
		}

	}

	 
	public void saveOperationTask(ScheduleScheme scheme,
			List<SOperationTask> opList) throws Exception {

		for (SOperationTask so : opList) {
			if (so.getObjectState() == BasicModel.OBJECTSTATE_TOBEDELETED) {
				removeOperationTask(scheme, so.getTaskUid());
			} else {

				if (so.getObjectState() == BasicModel.OBJECTSTATE_TOBEADDED) {
					addOperationTask(scheme, so);

				} else if (so.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
					SOperationTask oldOperationTask = scheme
							.getAllOperationTaskMap().get(so.getTaskUid());
					if (oldOperationTask == null)
						throw new Exception("找不到更新的工序任务！" + so);
					// 写日志
					// 旧的信息
					Element taskElement = new Element("OPERATIONTASK_PLANINFO");
					taskElement.setAttribute("partUid", oldOperationTask
							.getPartUid());
					taskElement.setAttribute("taskUid", oldOperationTask
							.getTaskUid());
					taskElement.setAttribute("drawingId", oldOperationTask
							.getDrawingId());
					if (oldOperationTask.getPartName() != null) {
						taskElement.setAttribute("partName", oldOperationTask
								.getPartName());
					} else {
						taskElement.setAttribute("partName", "");
					}
					// taskElement.setAttribute("partName", so.getPartName());
					taskElement.setAttribute("batchNum", oldOperationTask
							.getBatchNum());
					taskElement.setAttribute("operationIdDesc",
							oldOperationTask.getOperationIdDesc());
					if (oldOperationTask.getOperationId() != null) {
						taskElement.setAttribute("operationId", String
								.valueOf(oldOperationTask.getOperationId()));
					} else {
						taskElement.setAttribute("operationId", "");
					}
					taskElement.setAttribute("operationIdDesc",
							oldOperationTask.getOperationIdDesc());
					taskElement.setAttribute("taskName", oldOperationTask
							.getTaskName());
					if (oldOperationTask.getLocked() != null) {
						taskElement.setAttribute("locked", String
								.valueOf(oldOperationTask.getLocked()));
					}

					if (oldOperationTask.getSuccOperationStr() != null) {
						taskElement.setAttribute("succOperationStr",
								oldOperationTask.getSuccOperationStr());
					} else {
						taskElement.setAttribute("succOperationStr", "");
					}

					SimpleDateFormat formatDate = new SimpleDateFormat(
							"yyyy-MM-dd HH:mm:ss");
					if (oldOperationTask.getEarlyStart() == null) {
						taskElement.setAttribute("earlyStart", "");
					} else {
						taskElement.setAttribute("earlyStart", formatDate
								.format(oldOperationTask.getEarlyStart()));
					}
					if (oldOperationTask.getLateFinish() == null) {
						taskElement.setAttribute("lateFinish", "");
					} else {
						taskElement.setAttribute("lateFinish", formatDate
								.format(oldOperationTask.getLateFinish()));
					}
					taskElement.setAttribute("planQty", String
							.valueOf(oldOperationTask.getPlanQty()));
					taskElement.setAttribute("completeQty", String
							.valueOf(oldOperationTask.getCompleteQty()));
					taskElement.setAttribute("estiRunTime", String
							.valueOf(oldOperationTask.getEstiRunTime()));
					taskElement.setAttribute("estiPreTime", String
							.valueOf(oldOperationTask.getEstiPreTime()));
					taskElement.setAttribute("estiDelayTime", String
							.valueOf(oldOperationTask.getEstiDelayTime()));

					if (oldOperationTask.getDevice() != null) {
						taskElement.setAttribute("deviceUid", oldOperationTask
								.getDeviceUid());
						taskElement.setAttribute("deviceName", oldOperationTask
								.getDevice().getDeviceName());
					} else {
						taskElement.setAttribute("deviceUid", "");
						taskElement.setAttribute("deviceName", "");
					}
					if (oldOperationTask.getDeviceSeq() != null) {
						taskElement.setAttribute("deviceSeq", String
								.valueOf(oldOperationTask.getDeviceSeq()));
					} else {
						taskElement.setAttribute("deviceSeq", "");
					}
					taskElement.setAttribute("masterShop", oldOperationTask
							.getMasterShop());
					taskElement.setAttribute("masterShopName", oldOperationTask
							.getMasterShopName());
					taskElement.setAttribute("deviceClass", oldOperationTask
							.getDeviceClass());
					taskElement.setAttribute("deviceClassName",
							oldOperationTask.getDeviceClassName());

					/** * */
					updateOperationTask(scheme, so);

					// 新的信息
					Element newTaskElement = new Element("newPlanInfo");
					newTaskElement.setAttribute("partUid", so.getPartUid());
					newTaskElement.setAttribute("taskUid", so.getTaskUid());
					if (so.getDrawingId() != null) {
						newTaskElement.setAttribute("drawingId", so
								.getDrawingId());
					} else {
						newTaskElement.setAttribute("drawingId", "");
					}
					if (so.getPartName() != null) {
						newTaskElement.setAttribute("partName", so
								.getPartName());
					} else {
						newTaskElement.setAttribute("partName", "");
					}
					newTaskElement.setAttribute("batchNum", so.getBatchNum());
					newTaskElement.setAttribute("operationIdDesc", so
							.getOperationIdDesc());
					if (so.getOperationId() != null) {
						newTaskElement.setAttribute("operationId", String
								.valueOf(so.getOperationId()));
					} else {
						newTaskElement.setAttribute("operationId", "");
					}
					newTaskElement.setAttribute("taskName", so.getTaskName());
					if (so.getLocked() != null) {
						newTaskElement.setAttribute("locked", String.valueOf(so
								.getLocked()));
					} else {
						newTaskElement.setAttribute("locked", "");
					}

					if (so.getSuccOperationStr() != null) {
						newTaskElement.setAttribute("succOperationStr", so
								.getSuccOperationStr());
					} else {
						newTaskElement.setAttribute("succOperationStr", "");
					}
					if (so.getEarlyStart() == null) {
						newTaskElement.setAttribute("earlyStart", "");
					} else {
						newTaskElement.setAttribute("earlyStart", formatDate
								.format(so.getEarlyStart()));
					}
					if (so.getLateFinish() == null) {
						newTaskElement.setAttribute("lateFinish", "");
					} else {
						newTaskElement.setAttribute("lateFinish", formatDate
								.format(so.getLateFinish()));
					}
					newTaskElement.setAttribute("planQty", String.valueOf(so
							.getPlanQty()));
					newTaskElement.setAttribute("completeQty", String
							.valueOf(so.getCompleteQty()));
					newTaskElement.setAttribute("estiRunTime", String
							.valueOf(so.getEstiRunTime()));
					newTaskElement.setAttribute("estiPreTime", String
							.valueOf(so.getEstiPreTime()));
					newTaskElement.setAttribute("estiDelayTime", String
							.valueOf(so.getEstiDelayTime()));
					if (so.getDevice() != null) {
						newTaskElement.setAttribute("deviceUid", so
								.getDeviceUid());
						newTaskElement.setAttribute("deviceName", so
								.getDevice().getDeviceName());
					} else {
						newTaskElement.setAttribute("deviceUid", "");
						newTaskElement.setAttribute("deviceName", "");
					}
					if (so.getDeviceSeq() != null) {
						newTaskElement.setAttribute("deviceSeq", String
								.valueOf(so.getDeviceSeq()));
					} else {
						newTaskElement.setAttribute("deviceSeq", "");
					}
					if (so.getMasterShop() != null) {
						newTaskElement.setAttribute("masterShop", so
								.getMasterShop());
					} else {
						newTaskElement.setAttribute("masterShop", "");
					}
					if (so.getDeviceClass() != null) {
						newTaskElement.setAttribute("deviceClass", so
								.getDeviceClass());
					} else {
						newTaskElement.setAttribute("deviceClass", "");
					}
					if (so.getDeviceClassName() != null) {
						newTaskElement.setAttribute("deviceClassName", so
								.getDeviceClassName());
					} else {
						newTaskElement.setAttribute("deviceClassName", "");
					}
					taskElement.addContent(newTaskElement);

					this.scheduleEventManager.writeOperLog(scheme,
							ScheduleEvent.EVENTTYPE_OPERATIONTASK_PLANINFO,
							taskElement);
				}
			}
		}
	}

	@Transactional
	 
	public <T extends SOperationTask> T addOperationTask(ScheduleScheme scheme,
			T so) throws Exception {
		/*
		 * lqm todo 用了泛型还需要用强转，明显是不专业的用法
		 */

		Class<T> c = (Class<T>) so.getClass();
		T newSo = c.newInstance();
		ObjectOperation.copyAttributes(so, newSo);

		if (newSo.getPlanStart() != null && newSo.getPlanFinish() != null
				&& newSo.getPlanFinish().before(newSo.getPlanStart()))
			throw new Exception("计划结束时间不能晚于计划开始时间！" + newSo.toFriendlyString());

		newSo.setScheme(scheme);
		if (newSo.getDeptUid() == null)
			newSo.setDeptUid(scheme.getDeptUid());
		if (newSo.getTaskUid() == null)
			newSo.setTaskUid(IdentityGenerator.GetIdentityString());
		if (newSo.getTaskState() == null)
			newSo.setTaskState(SOperationTask.TASKSTATE_READY);

		// 处理设备问题&& !(newTask.getDeviceUid().equals(originalTask.getDeviceUid())
		if (newSo.getDeviceUid() != null) {
			SDevice device = scheme.getDeviceMap().get(newSo.getDeviceUid());
			if (device != null) {
				newSo.setDevice(device);
				newSo.setDeviceUid(device.getDeviceUid());
				// originalTask.setDeviceClass(device.getDeviceClass());
				// originalTask.setDeviceClassName(device.getDeviceClassName());

			}
		}

		if (newSo.getDeviceClass() != null) {
			// setTaskMasterShop(newSo);
			log.debug("updateOperationTask更新工序任务 开始计算可选资源列表！");
			this.calcAlterResourceList(newSo);
		}

		// 创建缺省工序
		// by lqm todo
		// 很无赖的选择，其实这里没有必要产生op,主要是为了能够增加工序限制
		// todo
		// 这条opuid其实专门为了强制设置工序为做，
		// 可以将其移到强制工序中去
		if (newSo.getOpUid() == null) {
			// taskDao.addOperation(newSo);
		}

		newSo.calTaskWork();

		if (newSo.getTaskScheduleState() == SOperationTask.TASKSCHEDULESTATE_STARTED)
			this.intoSchedule(newSo);
		scheme.getAllOperationTaskMap().put(newSo.getTaskUid(), newSo);
		this.add(newSo);

		if (SOperationTask.TASKTYPE_TEMPTASK.equals(newSo.getTaskType()))
			scheme.getScheduleTempTaskList().add(newSo);
		else if (SOperationTask.TASKTYPE_COTASK.equals(newSo.getTaskType()))
			scheme.getCoTaskMap().put(newSo.getTaskUid(), newSo);

		return newSo;

	}

	private void setElementAttribute(Element taskElement, String nodeId,
			Object nodeValue) {
		if (nodeValue == null) {
			taskElement.setAttribute(nodeId, "");
		} else
			taskElement.setAttribute(nodeId, String.valueOf(nodeValue));
	}

	 
	public void publishCoTask(String scheduleUid, String taskUid)
			throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme == null) {
			throw new Exception("找不到调度方案!");
		}

		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);
		if (operationTask == null)
			throw new Exception("找不到指定工序任务:" + taskUid);

		String strMaxCoTaskPublishDistance = "";
//		SysUtil
//				.getProperty("maxCoTaskPublishDistance");
		if (!StringUtils.isEmpty(strMaxCoTaskPublishDistance)) {
			maxCoTaskPublishDistance = Integer
					.valueOf(strMaxCoTaskPublishDistance);
			if (maxCoTaskPublishDistance != null
					&& operationTask.getTaskDistance() > maxCoTaskPublishDistance) {
				throw new Exception("任务工序距离大于" + maxCoTaskPublishDistance
						+ "，无法进行委外协作！" + operationTask.toFriendlyString());
			}
		}

		operationTask.setCoTaskState(SOperationTask.COTASKSTATE_PUBLISHED);
		// 将备注清空，可删除拒绝原因
		operationTask.setNotes("");
		// TODO
		// 记住， HH千万不能小写
		// by lqm todo
		SimpleDateFormat formatDate = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");

		ScheduleEvent scheduleEvent = new ScheduleEvent();
		// scheduleEvent.setScheduleUid("schedule-"
		// + operationTask.getMasterShop());
		scheduleEvent.setEventType(ScheduleEvent.EVENTTYPE_PUBLISH_COTASK);
		scheduleEvent.setKeyUid(operationTask.getTaskUid());

		Element taskElement = new Element("Task");
		setElementAttribute(taskElement, "taskUid", operationTask.getTaskUid());
		setElementAttribute(taskElement, "taskName", operationTask
				.getTaskName());
		setElementAttribute(taskElement, "partUid", operationTask.getPartUid());

		setElementAttribute(taskElement, "drawingId", operationTask
				.getDrawingId());

		setElementAttribute(taskElement, "partName", operationTask
				.getPartName());

		setElementAttribute(taskElement, "batchNum", operationTask
				.getBatchNum());

		setElementAttribute(taskElement, "operationIdDesc", operationTask
				.getOperationIdDesc());
		setElementAttribute(taskElement, "deviceClass", operationTask
				.getDeviceClass());

		setElementAttribute(taskElement, "deviceClassName", operationTask
				.getDeviceClassName());

		setElementAttribute(taskElement, "deptUid",
				operationTask.getDeptUid() == null ? scheme.getDeptUid()
						: operationTask.getDeptUid());

		setElementAttribute(taskElement, "deptName", operationTask
				.getDeptName());

		setElementAttribute(taskElement, "masterShop", operationTask
				.getMasterShop());

		setElementAttribute(taskElement, "masterShopName", operationTask
				.getMasterShopName());

		setElementAttribute(taskElement, "opUid", operationTask.getOpUid());

		setElementAttribute(taskElement, "planQty", operationTask.getPlanQty());

		setElementAttribute(taskElement, "completeQty", operationTask
				.getCompleteQty());

		setElementAttribute(taskElement, "estiPreTime", operationTask
				.getEstiPreTime());

		setElementAttribute(taskElement, "estiRunTime", operationTask
				.getEstiRunTime());

		setElementAttribute(taskElement, "planGrade", operationTask
				.getPlanGrade());

		// 传递优先级与松弛系数
		setElementAttribute(taskElement, "priority", operationTask
				.getPriority());
		setElementAttribute(taskElement, "slackFactor", operationTask
				.getSlackFactor());

		setElementAttribute(taskElement, "planGrade", operationTask
				.getPlanGrade());
		Date dt;
		// 取前道工序结束作为最早开始时间
		if (allowPublishCoTaskEarlyStart != null
				&& allowPublishCoTaskEarlyStart) {
			dt = (operationTask.getEarlyStart() == null ? operationTask
					.getPredFinish() : operationTask.getEarlyStart());
			setElementAttribute(taskElement, "earlyStart", (dt == null ? ""
					: formatDate.format(dt)));
		}
		if (operationTask.getParentTask() != null
				&& coTaskUsePartTaskLateFinish != null
				&& coTaskUsePartTaskLateFinish) {

			dt = operationTask.getParentTask().getLateFinish();
			setElementAttribute(taskElement, "lateFinish", (dt == null ? ""
					: formatDate.format(dt)));
		} else {
			// 取后道工序开始结束作为最早结束时间
			dt = operationTask.getLateFinish() == null ? operationTask
					.getSuccStart() : operationTask.getLateFinish();
			setElementAttribute(taskElement, "lateFinish", (dt == null ? ""
					: formatDate.format(dt)));
		}
		setElementAttribute(taskElement, "notes", operationTask.getNotes());

		Format format = Format.getCompactFormat();
		format.setEncoding("UTF-8");
		format.setIndent("  ");
		XMLOutputter outputter = new XMLOutputter(format);

		scheduleEvent.setEventContent(outputter.outputString(taskElement));
		scheduleEvent.setEventState(ScheduleEvent.EVENTSTATE_DRAFT);

		scheduleEvent.setSourceUid(scheduleUid);

//		scheduleEvent.setCreatorUid(SysUtil.getSessionEmployeeId());
		scheduleEvent.setCreateTime(new Date());

		this.scheduleEventManager.addScheduleEvent(operationTask
				.getMasterShop(), scheduleEvent);
	}

	 
	public void autoPublishCoTask(ScheduleScheme scheme) throws Exception {

		// TODO Auto-generated method stub
		SOperationTask soTask = new SOperationTask();
		soTask.setPriority(null);
		soTask.setDrawingId(null);
		soTask.setBatchNum(null);
		soTask.setPlanStart(null);
		soTask.setPlanGrade(null);
		soTask.setMasterShop(null);
		soTask.setCoTaskState(null);
		soTask.setWorkCenterUid(null);
		try {
			List<SOperationTask> cooperationTasks = this.filterOutTask(scheme,
					scheme.getScheduleOperationTasks(), soTask);
			for (SOperationTask so : cooperationTasks) {
				// 草稿、发布和接收的才自动发送
				if (so.getTaskDistance() == 0 && so.getCoTaskState() != null
						&& so.getCoTaskState() < 2) {
					this
							.publishCoTask(scheme.getScheduleUid(), so
									.getTaskUid());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("自动发布协作任务出错！");
		}

	}

	 
	public void unPublishCoTask(String scheduleUid, String taskUid)
			throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}

		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);

		if (operationTask.getCoTaskState() != SOperationTask.COTASKSTATE_PUBLISHED)
			throw new Exception("只有状态为 已发布 的任务才能够取消！");

		ScheduleEvent scheduleEvent = new ScheduleEvent();
		scheduleEvent.setScheduleUid("schedule-"
				+ operationTask.getMasterShop());
		scheduleEvent.setEventType(ScheduleEvent.EVENTTYPE_UNPUBLISH_COTASK);
		operationTask.setCoTaskState(SOperationTask.COTASKSTATE_DRAG);
		scheduleEvent.setKeyUid(operationTask.getTaskUid());
		StringBuilder strContent = new StringBuilder();
		strContent.append("<Task ");
		strContent.append(" taskUid='" + operationTask.getTaskUid() + "' ");
		strContent.append(" notes='"
				+ (operationTask.getNotes() == null ? "" : operationTask
						.getNotes()) + "' ");
		strContent.append(" />");

		scheduleEvent.setEventContent(strContent.toString());
		scheduleEvent.setEventState(ScheduleEvent.EVENTSTATE_DRAFT);

		scheduleEvent.setSourceUid(scheduleUid);

//		scheduleEvent.setCreatorUid(SysUtil.getSessionEmployeeId());
		scheduleEvent.setCreateTime(new Date());

		this.scheduleEventManager.addScheduleEvent(operationTask
				.getMasterShop(), scheduleEvent);

	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	 
	public void cancelAllDispatch(ScheduleScheme scheme, SDevice device)
			throws Exception {
		// // 更新派工信息
		// // 删除任务状态为“已派工”的派工记录
		// // 已开始的任务自动锁定
		// assignmentDeviceManager.deleteUnWorkAssn(scheme.getDeptUid());

		// 清除所有派工状态
		for (SOperationTask operationTask : scheme.getAllOperationTaskMap()
				.values()) {
			if (operationTask.getTaskState() == SOperationTask.TASKSTATE_DISPATCHED
					&& operationTask.getDeviceUid() != null
					&& operationTask.getDeviceUid().equals(
							device.getDeviceUid()))
				try {
					this.cancelDispatchTask(scheme, operationTask);
				} catch (RuntimeException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

		}
		// 一般情况下这里应该为空

		try {
//			assignmentDeviceManager.deleteDeviceUnFinishedAssignments(device
//					.getDeviceUid());
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Transactional
	 
	public void cancelDispatchTask(ScheduleScheme scheme,
			SGroupOperationTask groupTask) throws Exception {
		List<SOperationTask> memberTasks = groupTask.getMemberTasks();
		if (memberTasks != null && memberTasks.size() > 0) {
			for (SOperationTask memberTask : memberTasks) {
				this.cancelDispatchTask(scheme, memberTask);
			}
		}

	}

	 
	@Transactional
	public void dispatchTask(ScheduleScheme scheme,
			SGroupOperationTask groupTask) throws Exception {
		List<SOperationTask> memberTasks = groupTask.getMemberTasks();
		if (memberTasks != null && memberTasks.size() > 0) {
			for (SOperationTask memberTask : memberTasks) {
				this.dispatchTask(scheme, memberTask);
			}
		}

	}

	public OperationTaskDao getOperationTaskDao() {
		return operationTaskDao;
	}

	public void setOperationTaskDao(OperationTaskDao operationTaskDao) {
		this.operationTaskDao = operationTaskDao;
	}

	 
	@Transactional
	public void cancelDispatchTask(ScheduleScheme scheme,
			STempOperationTask tempTask) throws Exception {
		// TODO Auto-generated method stub
		// OperationTask
		// oo=(OperationTask)this.operationTaskManager.getById(tempTask.getTaskUid());
		// 创建一个任务
		// if(oo==null)return;
		this.cancelDispatchTask(scheme, (SOperationTask) tempTask);
		// this.operationTaskManager.delete(oo);

	}

	 
	@Transactional
	public void dispatchTask(ScheduleScheme scheme, STempOperationTask tempTask)
			throws Exception {
		// TODO Auto-generated method stub
		OperationTask oo = (OperationTask) this.operationTaskManager
				.getById(tempTask.getTaskUid());
		// 创建一个任务
		if (oo == null) {
			oo = new OperationTask();
			oo.setUuid(tempTask.getTaskUid());
			oo.setPartUid(tempTask.getPartUid());
			oo.setBatchNum(tempTask.getBatchNum());
			oo.setOperationIdDesc(tempTask.getOperationIdDesc());
			oo.setTaskName(tempTask.getTaskName());
//			oo.setTaskState((long)STempOperationTask.TASKSTATE_READY);
			oo.setTaskType(tempTask.TASKTYPE_TEMPTASK);
			oo.setMasterShopUid(scheme.getDeptUid());
			oo.setDeptUid(scheme.getDeptUid());
//			oo.setPlanQty(tempTask.getPlanQty().doubleValue());
			this.getOperationTaskManager().add(oo);

		}

		String creatorUid = "";//SysUtil.getSessionEmployeeId();
//		assignmentDeviceManager.addAssn(oo.getUuid(), tempTask.getDeviceUid(),
//				null, tempTask.getPlanStart(), tempTask.getPlanFinish(),
//				(double) oo.getPlanQty(), creatorUid);

		tempTask.setTaskState(SOperationTask.TASKSTATE_WAITING);

	}

	public OperationTaskManager getOperationTaskManager() {
		return operationTaskManager;
	}

	public void setOperationTaskManager(
			OperationTaskManager operationTaskManager) {
		this.operationTaskManager = operationTaskManager;
	}

	 
	public List<SOperationTask> filterInTask(ScheduleScheme scheme,
			Collection<SOperationTask> operationTaskList,
			SOperationTask likeTask) {
		List<SOperationTask> opListForReturn = new ArrayList<SOperationTask>();

		String drawingId = likeTask.getDrawingId();
		String batchNum = likeTask.getBatchNum();
		Date lateFinish = likeTask.getLateFinish();
		Integer planGrade = likeTask.getPlanGrade();
		Integer priority = likeTask.getPriority();
		String deptId = likeTask.getDeptUid();
		Integer coTaskState = likeTask.getCoTaskState();
		String workCenterUid = likeTask.getWorkCenterUid();
		List<WorkCenter> workCenterList = new ArrayList<WorkCenter>();
		// hba 可以按照工作中心过滤厂内协作（allCNXZ）和厂外协作（allCWXZ）的所有工序任务
//		if (workCenterUid != null && !workCenterUid.equals("")) {
//			if (workCenterUid.equals("allCNXZ")) {
//				workCenterList = workCenterDao.getCoWorkCenters();
//			} else if (workCenterUid.equals("allCWXZ")) {
//				workCenterList = workCenterDao.getWorkCentersByDeptUid("CWXZ",
//						null);
//			}
//		}

		for (SOperationTask operationTask : operationTaskList) {

			try {
				if (log.isDebugEnabled()) {
					if (operationTask.getTaskUid().equals(
							"2975e4a1-1923-4a59-a9be-d981fe07c079")) {
						log.debug("aaaaa");
					}
				}
				// if
				// ((scheme.getDeptUid()).equals(operationTask.getMasterShop()))
				// continue;

				if (!StringOper.equals(drawingId, operationTask.getDrawingId()))
					continue;
				if (!StringOper.equals(batchNum, operationTask.getBatchNum()))
					continue;

				if (deptId != null && !deptId.equals("")
						&& !deptId.equals(operationTask.getDeptUid()))
					continue;

				// hba 可以按照工作中心过滤厂内协作（allCNXZ）和厂外协作（allCWXZ）的所有工序任务
				if (workCenterUid != null && !workCenterUid.equals("")) {
					boolean isContinue = true;
					if (workCenterList != null && workCenterList.size() > 0) {
						for (WorkCenter wc : workCenterList) {
							if (wc.getWorkCenterUid().equals(
									operationTask.getWorkCenterUid())) {
								isContinue = false;
								break;
							}
						}
						if (isContinue) {
							continue;
						}
					} else if (!workCenterUid.equals(operationTask
							.getWorkCenterUid())) {
						continue;
					}
				}

				if (coTaskState != null
						&& !operationTask.getCoTaskState().equals(coTaskState))
					continue;

				if (lateFinish != null && operationTask.getLateFinish() != null
						&& lateFinish.after(operationTask.getLateFinish()))
					continue;

				if (priority != null && priority > 0) {
					if (operationTask.getPriority() == null)
						continue;

					int pp = Integer.parseInt(String.valueOf(
							operationTask.getPriority()).substring(0, 1));
					if (!priority.equals(pp))
						continue;
				}

				opListForReturn.add(operationTask);
			} catch (Exception e) {
				log.error("过滤协作任务发生错误", e);
			}
		}

		try {
			// add by zy 用于按照状态排序
			List<CoTaskSort> opListForSort = new ArrayList<CoTaskSort>();
			for (SOperationTask operationTask : opListForReturn) {
				CoTaskSort coTask = new CoTaskSort();

				switch (operationTask.getCoTaskState()) {
				case SOperationTask.COTASKSTATE_REFUSED: {// 已经拒绝
					coTask.mark = 1;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_DRAG: { // 草稿
					coTask.mark = 2;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_FEEDBACKED: {// 已经反馈
					coTask.mark = 3;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_PUBLISHED: {// 已经发布
					coTask.mark = 4;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_RECEIVED: {// 已经接收
					coTask.mark = 5;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_CANCELED: {// 已经取消
					coTask.mark = 6;
					coTask.operationTask = operationTask;
					break;
				}

				}

				opListForSort.add(coTask);

			}

			opListForReturn.clear();

			Collections.sort(opListForSort, new Comparator<CoTaskSort>() {

				 
				public int compare(CoTaskSort o1, CoTaskSort o2) {

					// TODO Auto-generated method stub
					return o1.getMark().compareTo(o2.getMark());
				}
			});

			for (CoTaskSort coTaskSort : opListForSort) {
				opListForReturn.add(coTaskSort.getOperationTask());

			}
		} catch (Exception e) {
			log.error("协助排序发生错误", e);
			// e.printStackTrace();
		}

		return opListForReturn;
	}

	private class CoTaskSort {
		private Integer mark;
		private SOperationTask operationTask;

		public Integer getMark() {
			return mark;
		}

		public void setMark(Integer mark) {
			this.mark = mark;
		}

		public SOperationTask getOperationTask() {
			return operationTask;
		}

		public void setOperationTask(SOperationTask operationTask) {
			this.operationTask = operationTask;
		}
	}

	 
	public List<SOperationTask> filterOutTask(ScheduleScheme scheme,
			Collection<SOperationTask> operationTaskList,
			SOperationTask likeTask) {

		String drawingId = likeTask.getDrawingId();
		String batchNum = likeTask.getBatchNum();
		Date planStart = likeTask.getPlanStart();
		Integer planGrade = likeTask.getPlanGrade();
		Integer priority = likeTask.getPriority();
		String masterShop = likeTask.getMasterShop();
		Integer coTaskState = likeTask.getCoTaskState();
		String workCenterUid = likeTask.getWorkCenterUid();
		List<WorkCenter> workCenterList = new ArrayList<WorkCenter>();
		// hba 可以按照工作中心过滤厂内协作（allCNXZ）和厂外协作（allCWXZ）的所有工序任务
		if (workCenterUid != null && !workCenterUid.equals("")) {
//			if (workCenterUid.equals("allCNXZ")) {
//				workCenterList = workCenterDao.getCoWorkCenters();
//			} else if (workCenterUid.equals("allCWXZ")) {
//				workCenterList = workCenterDao.getWorkCentersByDeptUid("CWXZ",
//						null);
//			}
		}
		List<SOperationTask> opListForReturn = new ArrayList<SOperationTask>();

		for (SOperationTask operationTask : operationTaskList) {
			if (log.isDebugEnabled()) {
				if (operationTask.getTaskUid().equals(
						"906cb483-5434-43a1-adbb-7657678caa5d")) {
					log.debug("aaaaa");
				}
			}
			// 非本部门请制的任务直接过滤掉
			if (operationTask.getDeptUid() != null
					&& (!(operationTask.getDeptUid().startsWith(scheme
							.getDeptUid()))))
				continue;
			// 主制部门是本部门的任务也直接过滤
			if ((scheme.getDeptUid()).equals(operationTask.getMasterShop()))
				continue;

			// 后面为过滤条件
			if (!StringOper.equals(drawingId, operationTask.getDrawingId()))
				continue;
			if (!StringOper.equals(batchNum, operationTask.getBatchNum()))
				continue;

			if (masterShop != null && !masterShop.equals("")
					&& !masterShop.equals(operationTask.getMasterShop()))
				continue;

			// hba 可以按照工作中心过滤厂内协作（allCNXZ）和厂外协作（allCWXZ）的所有工序任务
			if (workCenterUid != null && !workCenterUid.equals("")) {
				boolean isContinue = true;
				if (workCenterList != null && workCenterList.size() > 0) {
					for (WorkCenter wc : workCenterList) {
						if (wc.getWorkCenterUid().equals(
								operationTask.getWorkCenterUid())) {
							isContinue = false;
							break;
						}
					}
					if (isContinue) {
						continue;
					}
				} else if (!workCenterUid.equals(operationTask
						.getWorkCenterUid())) {
					continue;
				}
			}

			if (coTaskState != null
					&& !operationTask.getCoTaskState().equals(coTaskState))
				continue;

			if (planStart != null && operationTask.getPlanStart() != null
					&& planStart.before(operationTask.getPlanStart()))
				continue;

			if (priority != null && priority > 0) {
				if (operationTask.getPriority() == null)
					continue;

				int pp = Integer.parseInt(String.valueOf(
						operationTask.getPriority()).substring(0, 1));
				if (!priority.equals(pp))
					continue;
			}

			opListForReturn.add(operationTask);
		}
		try {
			// add by zy 用于按照状态排序
			List<CoTaskSort> opListForSort = new ArrayList<CoTaskSort>();
			for (SOperationTask operationTask : opListForReturn) {
				CoTaskSort coTask = new CoTaskSort();
				if (null == operationTask.getCoTaskState())
					continue;
				switch (operationTask.getCoTaskState()) {
				case SOperationTask.COTASKSTATE_REFUSED: {// 已经拒绝
					coTask.mark = 1;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_DRAG: { // 草稿
					coTask.mark = 2;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_FEEDBACKED: {// 已经反馈
					coTask.mark = 3;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_PUBLISHED: {// 已经发布
					coTask.mark = 4;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_RECEIVED: {// 已经接收
					coTask.mark = 5;
					coTask.operationTask = operationTask;
					break;
				}
				case SOperationTask.COTASKSTATE_CANCELED: {// 已经取消
					coTask.mark = 6;
					coTask.operationTask = operationTask;
					break;
				}

				}

				opListForSort.add(coTask);

			}

			opListForReturn.clear();

			Collections.sort(opListForSort, new Comparator<CoTaskSort>() {

				 
				public int compare(CoTaskSort o1, CoTaskSort o2) {

					// TODO Auto-generated method stub
					return o1.getMark().compareTo(o2.getMark());
				}
			});

			for (CoTaskSort coTaskSort : opListForSort) {
				opListForReturn.add(coTaskSort.getOperationTask());

			}
		} catch (Exception e) {
			log.error("委外排序发生错误", e);
		}

		return opListForReturn;
	}

	 
	public void receiveCoTask(String scheduleUid, String taskUid)
			throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}

		SOperationTask operationTask = scheme.getCoTaskMap().get(taskUid);
		if (operationTask == null)
			throw new Exception("找不到协作任务" + taskUid);

		operationTask.setCoTaskState(SOperationTask.COTASKSTATE_RECEIVED);
		// 同时设置其进入调度
		this.intoSchedule(operationTask);
		ScheduleEvent scheduleEvent = new ScheduleEvent();
		// scheduleEvent.setScheduleUid("schedule-" +
		// operationTask.getDeptUid());
		scheduleEvent.setEventType(ScheduleEvent.EVENTTYPE_RECEIVE_COTASK);
		scheduleEvent.setKeyUid(operationTask.getTaskUid());

		Element taskElement = new Element("Task");
		setElementAttribute(taskElement, "taskUid", operationTask.getTaskUid());

		setElementAttribute(taskElement, "notes",
				operationTask.getNotes() == null ? "" : operationTask
						.getNotes());

		Format format = Format.getCompactFormat();

		format.setEncoding("UTF-8");
		format.setIndent("  ");
		XMLOutputter outputter = new XMLOutputter(format);

		scheduleEvent.setEventContent(outputter.outputString(taskElement));

		// StringBuilder strContent = new StringBuilder();
		// strContent.append("<Task ");
		// strContent.append(" taskUid='" + operationTask.getTaskUid() + "' ");
		// strContent.append(" notes='" + (operationTask.getNotes() == null ? ""
		// : operationTask.getNotes()) + "' ");
		// strContent.append(" />");
		//
		// scheduleEvent.setEventContent(strContent.toString());
		scheduleEvent.setEventState(ScheduleEvent.EVENTSTATE_DRAFT);

		scheduleEvent.setSourceUid(scheduleUid);

//		scheduleEvent.setCreatorUid(SysUtil.getSessionEmployeeId());
		scheduleEvent.setCreateTime(new Date());

		this.scheduleEventManager.addScheduleEvent(operationTask.getDeptUid(),
				scheduleEvent);

	}

	 
	public void refuseCoTask(String scheduleUid, String taskUid)
			throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}

		SOperationTask operationTask = scheme.getCoTaskMap().get(taskUid);
		if (operationTask == null)
			throw new Exception("找不到协作任务" + taskUid);
		// 此处应该提示填写拒绝原因
		if (operationTask.getNotes() == null || operationTask.getNotes() == "") {
			throw new Exception("请在备注中填写拒绝原因!");
		}

		// 直接移除
		this.removeOperationTask(operationTask, true);

		ScheduleEvent scheduleEvent = new ScheduleEvent();
		// scheduleEvent.setScheduleUid("schedule-" +
		// operationTask.getDeptUid());
		scheduleEvent.setEventType(ScheduleEvent.EVENTTYPE_REFUSE_COTASK);
		scheduleEvent.setKeyUid(operationTask.getTaskUid());
		StringBuilder strContent = new StringBuilder();
		Element taskElement = new Element("Task");
		setElementAttribute(taskElement, "taskUid", operationTask.getTaskUid());

		setElementAttribute(taskElement, "notes",
				operationTask.getNotes() == null ? "" : operationTask
						.getNotes());

		Format format = Format.getCompactFormat();

		format.setEncoding("UTF-8");
		format.setIndent("  ");
		XMLOutputter outputter = new XMLOutputter(format);

		scheduleEvent.setEventContent(outputter.outputString(taskElement));
		scheduleEvent.setEventState(ScheduleEvent.EVENTSTATE_DRAFT);

		scheduleEvent.setSourceUid(scheduleUid);

//		scheduleEvent.setCreatorUid(SysUtil.getSessionEmployeeId());
		scheduleEvent.setCreateTime(new Date());

		this.scheduleEventManager.addScheduleEvent(operationTask.getDeptUid(),
				scheduleEvent);

	}

	public PriorityCalc getPriorityCalc() {
		return priorityCalc;
	}

	public void setPriorityCalc(PriorityCalc priorityCalc) {
		this.priorityCalc = priorityCalc;
	}

	public ScheduleEventManager getScheduleEventManager() {
		return scheduleEventManager;
	}

	public void setScheduleEventManager(
			ScheduleEventManager scheduleEventManager) {
		this.scheduleEventManager = scheduleEventManager;
	}

	 
	@Transactional
	public void feedbackCoTask(String scheduleUid, String taskUid)
			throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}

		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);

		operationTask.setCoTaskState(SOperationTask.COTASKSTATE_FEEDBACKED);

		SimpleDateFormat formatDate = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");

		ScheduleEvent scheduleEvent = new ScheduleEvent();
		// scheduleEvent.setScheduleUid("schedule-" +
		// operationTask.getDeptUid());
		scheduleEvent.setEventType(ScheduleEvent.EVENTTYPE_FEEDBACK_COTASK);
		scheduleEvent.setKeyUid(operationTask.getTaskUid());
		// StringBuilder strContent = new StringBuilder();
		// strContent.append("<Task ");
		// strContent.append(" taskUid='" + operationTask.getTaskUid() + "' ");
		// // 开始时间
		// strContent.append(" coTaskState='" + operationTask.getCoTaskState() +
		// "' ");
		// // 开始时间
		// strContent.append(" planStart='" + (operationTask.getPlanStart() ==
		// null ? "" : formatDate.format(operationTask.getPlanStart())) + "' ");
		// // 结束时间
		// strContent.append(" planFinish='" + (operationTask.getPlanFinish() ==
		// null ? "" : formatDate.format(operationTask.getPlanFinish())) + "'
		// ");
		// strContent.append(" notes='" + (operationTask.getNotes() == null ? ""
		// : operationTask.getNotes()) + "' ");
		// strContent.append(" />");
		//
		// scheduleEvent.setEventContent(strContent.toString());

		Element taskElement = new Element("Task");
		setElementAttribute(taskElement, "taskUid", operationTask.getTaskUid());
		setElementAttribute(taskElement, "coTaskState", String
				.valueOf(operationTask.getCoTaskState()));
		// 开始时间
		setElementAttribute(taskElement, "planStart", (operationTask
				.getPlanStart() == null ? "" : formatDate.format(operationTask
				.getPlanStart())));
		setElementAttribute(taskElement, "planFinish", (operationTask
				.getPlanFinish() == null ? "" : formatDate.format(operationTask
				.getPlanFinish())));
		setElementAttribute(taskElement, "notes",
				operationTask.getNotes() == null ? "" : operationTask
						.getNotes());

		Format format = Format.getCompactFormat();

		format.setEncoding("UTF-8");
		format.setIndent("  ");
		XMLOutputter outputter = new XMLOutputter(format);

		scheduleEvent.setEventContent(outputter.outputString(taskElement));

		scheduleEvent.setEventState(ScheduleEvent.EVENTSTATE_DRAFT);
		scheduleEvent.setSourceUid(scheduleUid);
		scheduleEvent.setSourceType("用户反馈协作任务");
//		scheduleEvent.setCreatorUid(SysUtil.getSessionEmployeeId());
		scheduleEvent.setCreateTime(new Date());

		this.scheduleEventManager.addScheduleEvent(operationTask.getDeptUid(),
				scheduleEvent);

	}

	 
	public void autoFeedbackCoTask(String scheduleUid, String taskUid,
			Date startDate, Date finishDate) throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme == null) {
			throw new Exception("Error! Can not find the schedule scheme!");
		}

		Calendar calendar = Calendar.getInstance();

		if (startDate == null) {
			calendar.setTime(new Date());
			calendar.add(Calendar.WEEK_OF_YEAR, 1);
			calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
			calendar.set(Calendar.HOUR_OF_DAY, 0);
			calendar.set(Calendar.MINUTE, 0);
			calendar.set(Calendar.SECOND, 0);
			calendar.set(Calendar.MILLISECOND, 0);
			startDate = calendar.getTime();
		} else {
			calendar.setTime(startDate);
			calendar.set(Calendar.HOUR_OF_DAY, 0);
			calendar.set(Calendar.MINUTE, 0);
			calendar.set(Calendar.SECOND, 0);
			calendar.set(Calendar.MILLISECOND, 0);
			startDate = calendar.getTime();
		}
		if (finishDate == null) {
			calendar.setTime(new Date());
			calendar.add(Calendar.WEEK_OF_YEAR, 2);
			calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
			calendar.set(Calendar.HOUR_OF_DAY, 23);
			calendar.set(Calendar.MINUTE, 59);
			calendar.set(Calendar.SECOND, 0);
			calendar.set(Calendar.MILLISECOND, 0);
			finishDate = calendar.getTime();
		} else {
			calendar.setTime(finishDate);
			calendar.set(Calendar.HOUR_OF_DAY, 0);
			calendar.set(Calendar.MINUTE, 0);
			calendar.set(Calendar.SECOND, 0);
			calendar.set(Calendar.MILLISECOND, 0);
			finishDate = calendar.getTime();
		}

		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);

		operationTask.setCoTaskState(SOperationTask.COTASKSTATE_FEEDBACKED);

		SimpleDateFormat formatDate = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");

		ScheduleEvent scheduleEvent = new ScheduleEvent();

		scheduleEvent.setEventType(ScheduleEvent.EVENTTYPE_FEEDBACK_COTASK);
		scheduleEvent.setKeyUid(operationTask.getTaskUid());

		Element taskElement = new Element("Task");
		setElementAttribute(taskElement, "taskUid", operationTask.getTaskUid());
		setElementAttribute(taskElement, "coTaskState", String
				.valueOf(operationTask.getCoTaskState()));

		// 判断计划开始时间是否在开始和结束时间内
		// 是则赋值计划开始和结束，不是则赋值最早开始时间

		if (operationTask.getPlanStart() != null
				&& operationTask.getPlanStart().after(startDate)
				&& operationTask.getPlanStart().before(finishDate)) {
			// 开始时间
			setElementAttribute(taskElement, "planStart", (operationTask
					.getPlanStart() == null ? "" : formatDate
					.format(operationTask.getPlanStart())));
			setElementAttribute(taskElement, "planFinish", (operationTask
					.getPlanFinish() == null ? "" : formatDate
					.format(operationTask.getPlanFinish())));
		} else {
			setElementAttribute(taskElement, "earlyStart", (operationTask
					.getPlanStart() == null ? "" : formatDate
					.format(operationTask.getPlanStart())));
		}

		setElementAttribute(taskElement, "notes",
				operationTask.getNotes() == null ? "" : operationTask
						.getNotes());
		Format format = Format.getCompactFormat();

		format.setEncoding("UTF-8");
		format.setIndent("  ");
		XMLOutputter outputter = new XMLOutputter(format);

		scheduleEvent.setEventContent(outputter.outputString(taskElement));

		scheduleEvent.setEventState(ScheduleEvent.EVENTSTATE_DRAFT);
		scheduleEvent.setSourceUid(scheduleUid);
		scheduleEvent.setSourceType("用户反馈协作任务");
//		scheduleEvent.setCreatorUid(SysUtil.getSessionEmployeeId());
		scheduleEvent.setCreateTime(new Date());

		this.scheduleEventManager.addScheduleEvent(operationTask.getDeptUid(),
				scheduleEvent);

	}

	public ScheduleDeviceManager getScheduleDeviceManager() {
		return scheduleDeviceManager;
	}

	public void setScheduleDeviceManager(
			ScheduleDeviceManager scheduleDeviceManager) {
		this.scheduleDeviceManager = scheduleDeviceManager;
	}

	 
	public SOperationTask groupTasks(List<SOperationTask> memberTasks,
			Integer groupType) throws Exception {
		// 允许一个任务也成组，然后逐渐加入
		if (memberTasks == null || memberTasks.size() < 1) {
			return null;
		}

		SGroupOperationTask newOperationTask;
		if (groupType != null
				&& groupType
						.equals(SOperationTask.TASKSCHEDULETYPE_PARALLELGROUP))
			newOperationTask = new SParallelGroup();
		else {
			newOperationTask = new SSerialGroup();
		}

		SOperationTask tempOperationTask = memberTasks.get(0);
		// todo
		// 尽量不要用beanUtils.copy会引起很多莫名其妙的对象引用问题
		// BeanUtils.copyProperties(newOperationTask, tempOperationTask);
		// 很好，取第一个任务
		ObjectOperation.copyAttributes(tempOperationTask, newOperationTask);
		newOperationTask.setTaskUid(IdentityGenerator.GetIdentityString());

		for (SOperationTask operationTask : memberTasks) {

			this.addMemberTask(newOperationTask, operationTask);

		}

		newOperationTask.setDevice(tempOperationTask.getDevice());
		// newOperationTask.setDevice(tempOperationTask.getDevice());

		// newOperationTask.setTaskName(tempOperationTask.getTaskName());
		// 父任务为空
		newOperationTask.setParentTask(null);
		// add by zy 按照交货期从小到大排序
		Collections.sort(memberTasks, new Comparator<SOperationTask>() {
			public int compare(SOperationTask o1, SOperationTask o2) {
				if (o1.getControlFinish().before(o2.getControlFinish()))
					return -1;
				else if (o1.getControlFinish().after(o2.getControlFinish()))
					return 1;
				else
					return 0;
			}
		});

		newOperationTask
				.setControlFinish(memberTasks.get(0).getControlFinish());
		newOperationTask.setLateFinish(memberTasks.get(0).getControlFinish());
		// todo
		// 可以多次递归成组，但也需要分层取消成组
		// 一定要注意清除
		// 用途beanUtils.copy会指向原对象，莫名其妙的清空
		// newOperationTask.getMemberTasks().clear();

		ScheduleScheme scheme = tempOperationTask.getScheme();
		newOperationTask.setScheme(scheme);

		if (newOperationTask.getDeptUid() == null)
			newOperationTask.setDeptUid(scheme.getDeptUid());

		this.init(scheme, newOperationTask);

		scheme.getGroupTaskList().add(newOperationTask);

		// 清空批次号，让其沿用缺省批次
		newOperationTask.setBatchNum(null);

		// this.calcAlterResourceList(newOperationTask);

		// 直接沿用原任务的可选资源列表
		// 这样会导致不能修改
		// calcAlterResourceList中会new出一个新对象ResourceList
		// newOperationTask.setAlterResourceList(tempOperationTask
		// .getAlterResourceList());

		// 将新任务加入调度序列
		this.intoSchedule(newOperationTask);
		// 将成员任务移出调度序列
		// addmemeberTask已经自动将其移出
		// this.outSchedule(memberTasks);
		// 直接添加到数据库中
		scheme.getAllOperationTaskMap().put(newOperationTask.getTaskUid(),
				newOperationTask);
		this.add(newOperationTask);
		this.update(memberTasks);

		return newOperationTask;

	}

	 
	public boolean canChangeDevice(SOperationTask operationTask) {
		// todo
		// 可能要根据规则加上已开始，已准备好，已派工等
		ScheduleScheme scheme = operationTask.getScheme();
		// 加上手动派工结果的判断 by hba
		// if (!(operationTask.getMasterShop().startsWith(scheme.getDeptUid())))
		// return true;

		if (operationTask.getDeviceUid() != null
				&& (operationTask.getCanChangeDevice() != null
						&& operationTask.getCanChangeDevice().equals(false)
						|| operationTask.getLocked().equals(1)
						|| operationTask.isStarted()
						|| (operationTask.getManualScheduleState() != null
								&& operationTask.getManualScheduleState() >= SOperationTask.MANUAL_SCHEDULED && operationTask
								.getDevice() != null)
						|| operationTask.getTaskState().equals(
								SOperationTask.TASKSTATE_INTERRUPTED)
						|| operationTask.getTaskState().equals(206)
						|| operationTask.getTaskState().equals(2061)
						|| operationTask.getTaskState().equals(2069) || scheme
						.isAllowDeviceQueueInterrupt()
						&& operationTask.getDeviceSeq() != null
						&& operationTask.getDeviceSeq() > 0))
			return false;
		return true;
	}

	 
	public void completeOfflinePrepare(ScheduleScheme scheme,
			SOperationTask operationTask, Date actualFinish) throws Exception {
		// TODO Auto-generated method stub
		operationTask.setTaskState(2069);
	}

	 
	public void startOfflinePrepare(ScheduleScheme scheme,
			SOperationTask operationTask, Date actualStart) throws Exception {
		// TODO Auto-generated method stub
		operationTask.setTaskState(2061);
	}

	 
	public void intoSchedule(List<SOperationTask> operationTaskList)
			throws Exception {
		if (operationTaskList != null && operationTaskList.size() > 0) {
			for (SOperationTask operationTask : operationTaskList) {
				this.intoSchedule(operationTask);
			}
		}

	}

	 
	public void intoSchedule(SOperationTask operationTask) throws Exception {
		ScheduleScheme scheme = operationTask.getScheme();
		operationTask
				.setTaskScheduleState(SOperationTask.TASKSCHEDULESTATE_STARTED);
		scheme.getScheduleOperationTasks().add(operationTask);
		// 直接存盘
		this.update(operationTask);

	}

	 
	public void outSchedule(List<SOperationTask> operationTaskList,
			Boolean isWaiting) throws Exception {
		if (operationTaskList != null && operationTaskList.size() > 0) {
			for (SOperationTask operationTask : operationTaskList) {
				this.outSchedule(operationTask, isWaiting);
			}
		}

	}

	 
	public void outSchedule(SOperationTask operationTask, Boolean isWaiting)
			throws Exception {
		if (operationTask.isRunning()) {
			return;
			// 事务也做的不好，避免对调度员的过多干扰
			// throw new Exception("该工序处于下发状态，不能从排产集合中移除！\\n 工序为:" +
			// operationTask.toFriendlyString());
		}
		// ScheduleScheme scheme = operationTask.getScheme();
		if (isWaiting == null || isWaiting.equals(true))
			operationTask
					.setTaskScheduleState(SOperationTask.TASKSCHEDULESTATE_WAITING);
		else
			operationTask
					.setTaskScheduleState(SOperationTask.TASKSCHEDULESTATE_NO);
		// if (scheme.getScheduleOperationTasks().contains(operationTask))
		operationTask.getScheme().getScheduleOperationTasks().remove(
				operationTask);

		// 锁定任务处理和设备队列处理
		// 只要未锁定则将其时间设置为空
		// lqm todo
		// 应该重用取消调度方法
		operationTask.setDeviceSeq(null);

		if (operationTask.getLocked() == 0 && !operationTask.isFinished()) {
			operationTask.setPlanStart(null);
			operationTask.setPlanFinish(null);
			operationTask.setPlanStartSegment(0);
			operationTask.setPlanFinishSegment(0);

			if (this.canChangeDevice(operationTask)) {
				operationTask.setDeviceUid(null);
				operationTask.setDevice(null);
			}
		}

		//
		// //对临时任务成组，协助任务成组缺乏考虑
		// if (operationTask.getGroupTask() != null)
		// this.deleteMemberTask(operationTask.getGroupTask(), operationTask);
		// if(operationTask instanceof SGroupOperationTask)
		// {
		//
		// }
		// 直接存盘
		this.update(operationTask);
	}

	public static void main(String args[]) {
		Set<String> s = new HashSet<String>();
		String str1 = "ssss";
		s.add(str1);
		System.out.println(s.remove(str1));
		System.out.println(s.remove("a"));

	}

	 
	public Date calFirstCheckStart(SOperationTask operationTask) {
		// TODO Auto-generated method stub
		if (operationTask.getDevice() == null) {
			log.error("计算首件检验开始时间时工序的设备信息不能为空！" + operationTask);
			return null;
		}

		if (!(operationTask.getTaskScheduleState() == SOperationTask.TASKSTATE_STARTED || operationTask
				.getTaskScheduleState() == SOperationTask.TASKSTATE_PREPARE_COMPLETED)) {
			log.debug("只有已开始的任务才需要计算首件检验开始时间！" + operationTask);
			return null;
		}

		Date firstCheckStart = null;
		// 如果已经完成装卡，则直接
		ScheduleScheme scheme = operationTask.getScheme();
		// Calendar calendar=Calendar.getInstance();
		// calendar.setTime(scheme.getScheduleCurrentTime());
		Date taskStart = operationTask.getActualStart() == null ? scheme
				.getScheduleCurrentTime() : operationTask.getActualStart();
		if (operationTask.getTaskState() == SOperationTask.TASKSTATE_PREPARE_COMPLETED) {
			firstCheckStart = this.scheduleDeviceManager.calFinishTime(
					operationTask.getDevice(), taskStart, operationTask
							.getEstiRunTime());
			// calendar.add(Calendar.MINUTE,(int)Math.round(operationTask.getEstiRunTime()));
			// firstCheckStart=calendar.getTime();
		} else if (operationTask.getTaskState() == SOperationTask.TASKSTATE_STARTED) {
			firstCheckStart = this.scheduleDeviceManager.calFinishTime(
					operationTask.getDevice(), taskStart, operationTask
							.getEstiPreTime()
							+ operationTask.getEstiRunTime());
			// calendar.add(Calendar.MINUTE,(int)Math.round(operationTask.getEstiRunTime()));
			// firstCheckStart=calendar.getTime();
		}
		// 是否要增加一个状态位，首件加工开始
		// lqm todo

		Calendar calendar = Calendar.getInstance();
		if (firstCheckStart.before(calendar.getTime())) {
			firstCheckStart = calendar.getTime();
			// lqm todo
			// 应该允许参数配置
			calendar.add(Calendar.HOUR, 2);
			firstCheckStart = calendar.getTime();
		}
		operationTask.setPlanFirstCheckStart(firstCheckStart);
		return firstCheckStart;
	}

	 
	public OperationTask getOOTask(SOperationTask operationTask) throws Exception {
		OperationTask oo = null;
		try {
			oo = (OperationTask) this.operationTaskDao.getById(operationTask
					.getTaskUid());
			if (oo == null)
				oo = this.operationTaskDao.getOperationTask(operationTask
						.getPartUid(), operationTask.getBatchNum(),
						operationTask.getOperationIdDesc());
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return oo;
	}

	 
	public Set<OperationTask> getOOTasks(SOperationTask operationTask) throws Exception {
		OperationTask oo;
		Set<OperationTask> ooTaskSet = new HashSet<OperationTask>();
		if (operationTask instanceof SGroupOperationTask) {
			SGroupOperationTask groupTask = (SGroupOperationTask) operationTask;
			List<SOperationTask> memberTasks = groupTask.getMemberTasks();
			if (memberTasks != null && memberTasks.size() > 0) {
				for (SOperationTask memberTask : memberTasks) {
					oo = this.getOOTask(memberTask);
					if (oo != null)
						ooTaskSet.add(oo);
				}
			}
			return ooTaskSet;
		}

		// 这个方法可以逐步淘汰
		// 用 TASKSCHEDULETYPE_COMBINEBATCH已经过时，应该有并行批和串行批
		// by lqm
		if (SOperationTask.TASKSCHEDULETYPE_COMBINEBATCH == operationTask
				.getTaskScheduleType()
				|| operationTask.getBatchNum().indexOf(",") > 0) {
			String[] strBatchNums = operationTask.getBatchNum().split(",");
			String[] strOperations = operationTask.getOperationIdDesc().split(
					"/");
			try {
				for (int i = 0; i < strBatchNums.length; i++) {
					oo = this.operationTaskDao.getOperationTask(operationTask
							.getPartUid(), strBatchNums[i], operationTask
							.getOperationIdDesc());
					if (oo != null)
						ooTaskSet.add(oo);
					else {
						for (int j = 0; j < strOperations.length; j++) {

							oo = this.operationTaskDao.getOperationTask(
									operationTask.getPartUid(),
									strBatchNums[i], strOperations[j]);
							if (oo != null)
								ooTaskSet.add(oo);
						}
					}
				}

			} catch (RuntimeException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return ooTaskSet;
		}

		if (operationTask.getOperationIdDesc().indexOf("/") > 0) {// 针对非合批但工序存在合并的情况

			try {
				oo = this.getOOTask(operationTask);
				if (oo != null)
					ooTaskSet.add(oo);
				else {
					String[] strOperations = operationTask.getOperationIdDesc()
							.split("/");
					for (int j = 0; j < strOperations.length; j++) {

						oo = this.operationTaskDao.getOperationTask(
								operationTask.getPartUid(), operationTask
										.getBatchNum(), strOperations[j]);
						if (oo != null)
							ooTaskSet.add(oo);

					}
				}
			} catch (RuntimeException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return ooTaskSet;
		}

		oo = this.getOOTask(operationTask);
		if (oo != null)
			ooTaskSet.add(oo);
		return ooTaskSet;

	}

	public SOperationTaskDao getScheduleOperationTaskDao() {
		return scheduleOperationTaskDao;
	}

	public void setScheduleOperationTaskDao(
			SOperationTaskDao scheduleOperationTaskDao) {
		this.scheduleOperationTaskDao = scheduleOperationTaskDao;
		// 如何采用面向对象的方法移除下面这句话呢？
		// todo
		// lqm
		// abstracemanager采用getDao(),manager去重载该方法
		this.basicDao = scheduleOperationTaskDao;
	}

	/**
	 * 取得某一道工序绝对的最早开始时间 主要用于能力估算 暂时算法比较简单 没有考虑复杂的网络，合批工序等情况
	 */
	public Date calAbsEalryStart(SOperationTask operationTask) {

		double sumWork = 0d;
		SOperationTask tmpOperationTask = operationTask;
		while (true) {
			sumWork += operationTask.getEstiTaskWork();
			Set<SOperationLink> predLinkSet = tmpOperationTask.getPredLinkSet();
			if (predLinkSet != null && predLinkSet.size() > 0) {
				// 只是取了第一条，不是很完备
				tmpOperationTask = predLinkSet.iterator().next()
						.getPredOperationTask();
			} else
				break;
		}

		Calendar c = Calendar.getInstance();
		c.add(Calendar.MINUTE, (int) (sumWork));

		return c.getTime();
	}

	 
	public List<SOperationTask> getMustDoList(SWorkCenter sWorkCenter,
			Date beforeDate, Double slackFactor, String drawingId,
			Integer maxTaskInstance) {
		// TODO Auto-generated method stub
		ScheduleScheme scheme = null;//sWorkCenter.getScheme();
		List<SOperationTask> mustDoList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleTaskList = scheme
				.getScheduleOperationTasks();
		for (SOperationTask so : scheduleTaskList) {
			if (so.getTaskUid().equals("6118d4e8-f41f-48cc-a50b-c3072714cd09")) {
				log.debug("aaaaaaaa");
			}
			if (so.getTaskState() >= 209)
				continue;
			if (so.getSWorkCenter() != null
					&& so.getSWorkCenter() == sWorkCenter) {

				if (so.getGroupTask() != null)
					continue;// 将已经纳入成组的任务一定要过滤掉

				if (!StringOper.equals(drawingId, so.getDrawingId()))
					continue;
				if (maxTaskInstance != null
						&& so.getTaskDistance() > maxTaskInstance)
					continue;

				if (beforeDate == null) {
					// 非能力计划，主要用于查询本工作中心上的任务
					// if
					// (so.getTaskUid().equals("6118d4e8-f41f-48cc-a50b-c3072714cd09"))
					mustDoList.add(so);
				} else {

					if (so.getControlFinish() != null
							&& so.getControlFinish().before(beforeDate))
						mustDoList.add(so);
					else if (so.getSlackFactor() != null && slackFactor != null
							&& so.getSlackFactor() <= slackFactor) {
						try {
							if (calAbsEalryStart(so).before(beforeDate))
								mustDoList.add(so);
						} catch (RuntimeException e) {
							// TODO Auto-generated catch block
							log.warn("计算可能要加入的任务序列时发生错误！");
						}
					}
				}

			}

		}

		Collections.sort(mustDoList, new Comparator<Object>() {
			public int compare(Object o1, Object o2) {
				SOperationTask operTask1 = (SOperationTask) o1;
				SOperationTask operTask2 = (SOperationTask) o2;
				int i = 0;

				if (operTask1.getTaskDistance() > operTask2.getTaskDistance()
						|| operTask1.getPriority() > operTask2.getPriority()
						|| (operTask1.getPriority() == operTask2.getPriority() && operTask1
								.getTaskDistance() > operTask2
								.getTaskDistance())
						|| (operTask1.getPriority() == operTask2.getPriority()
								&& operTask1.getTaskDistance() == operTask2
										.getTaskDistance() && operTask1
								.getSlackFactor() > operTask2.getSlackFactor())) {
					i = 1;
				}
				return i;
			}
		});

		return mustDoList;
	}

	/**
	 * 取消生产准备任务
	 * 
	 * @param so
	 * @throws Exception
	 */
	 
	@Transactional
	public void cancelPrepareTask(SOperationTask so, Set<OperationTask> ooSet)
			throws Exception {
		/*
		 * 任选一个任务与其关联
		 */
		// if (ooSet == null)
		// ooSet = this.getOOTasks(so);
		//
		// if (ooSet == null || ooSet.size()==0)
		// return;
		// for(OperationTask oo:ooSet)
		// {
//		this.prepareTaskManager.cancelPrepareTaskByScheduleTaskUid(so
//				.getTaskUid());
		// }
	}

	/**
	 * 保存或者更新生产准备任务
	 * 
	 * @param so
	 * @throws Exception
	 */
	 
	@Transactional
	public void saveOrUpdatePrepareTask(SOperationTask so,
			Set<OperationTask> ooSet) throws Exception {
		/*
		 * 任选一个任务与其关联
		 */
		if (ooSet == null)
			ooSet = this.getOOTasks(so);

		if (ooSet == null || !ooSet.iterator().hasNext())
			return;

		/*
		 * 任选一个任务与其关联
		 */
		// lqm todo
		// 暂时先对所有任务都产生
		// OperationTask oo = ooSet.iterator().next();
		// PrepareTask prepareTask = new PrepareTask();
		// //直接用任务号作为
		// prepareTask.setPrepareTaskUid(IdentityGenerator.GetIdentityUUID());
		// prepareTask.setPrepareTaskType("301");
		// prepareTask.setPrepareTaskState("205");
		// prepareTask.setResuid(so.getDeviceUid());
		// prepareTask.setTaskPlanStart(so.getPlanStart());
		// prepareTask.setFinalTime(so.getPlanStart());
		// prepareTask.setTaskBatchnum(so.getBatchNum());
		// prepareTask.setTaskPartNumber(so.getPartUid());
		//
		//
		//
		// prepareTask.setPriority(0l);
		// prepareTask.setOperationId((double) so.getOperationId());
		// prepareTask.setOperationIddesc(so.getOperationIdDesc());
		// prepareTask.setTaskDrawingid(so.getDrawingId());
		//
		// prepareTask.setRouting(oo.getRoutingUid());
		// prepareTask.setOpuid(oo.getOperationUid());
		//
		//
		// prepareTask.setTaskUid(oo.getUuid());
		// prepareTask.setScheduleTaskUid(so.getTaskUid());
		//
		// this.prepareTaskManager.saveOrUpdateSortTask(prepareTask);
//		String creatorUid = SysUtil.getSessionEmployeeId();

		for (OperationTask oo : ooSet) {
//			this.prepareTaskManager.saveOrUpdatePrepareTask(so.getTaskUid(), oo
//					.getTaskUid(), creatorUid);
		}
	}

	public PrepareTaskManager getPrepareTaskManager() {
		return prepareTaskManager;
	}

	public void setPrepareTaskManager(PrepareTaskManager prepareTaskManager) {
		this.prepareTaskManager = prepareTaskManager;
	}

	 
	public void clearSeq(ScheduleScheme scheme) throws Exception {
		// TODO Auto-generated method stub
		for (SOperationTask so : scheme.getAllOperationTaskMap().values()) {
			so.setDeviceSeq(null);
			so.setCalDeviceSeq(null);
		}
	}

	 
	public void clearDeviceSeq(ScheduleScheme scheme, String deviceUid)
			throws Exception {
		if (deviceUid == null || deviceUid.equals("")) {
			return;
		}
		for (SOperationTask so : scheme.getAllOperationTaskMap().values()) {
			if (so.getDeviceUid() != null
					&& so.getDeviceUid().equals(deviceUid)) {
				so.setDeviceSeq(null);
				so.setCalDeviceSeq(null);
				so.setAssnPriority(3);
			}
		}
	}

	/**
	 * 初始化一个调度中的工序任务 主要是完成一些对象的初始化,工时,可选设备列表等
	 * 
	 * @param scheme
	 * @param operationTask
	 */
	public void init(ScheduleScheme scheme, SOperationTask operationTask) {
		if (log.isInfoEnabled()) {
			if (operationTask.getTaskUid().equals(
					"c8d6412a-31e1-4c5f-a486-e543bd84b0d6"))
				log.debug("aaaa");
		}

		if (operationTask.getDeviceUid() != null) {
			SDevice device = scheme.getDeviceMap().get(
					operationTask.getDeviceUid());
			if (device != null) {
				operationTask.setDevice(device);
			}
		}

		if (operationTask.getCalUid() != null) {

			String strCalUid = operationTask.getCalUid();
			try {
				SCalendar scalendar = scheme.getCalendarMap().get(strCalUid);
				if (scalendar == null) {
					scalendar = scheduleCalendarManager.initCalendar(scheme,
							strCalUid);
					scheme.getCalendarMap().put(strCalUid, scalendar);
				}

				operationTask.setCalendar(scalendar);
			} catch (Exception e) {
				log.error("调度日历初始化时发生错误,日历编号为：" + strCalUid + "\n"
						+ e.getMessage());
				e.printStackTrace();
			}
		}
		if (operationTask.getDeviceClass() == null) {
			operationTask.setDeviceClass("cooperationCenter");
			// 应该分成几类工作中心
			operationTask.setDeviceClassName("外协中心");
			operationTask.setMasterShop("WX");
			operationTask.setMasterShopName("外协");
		}

		// todo计算自动平顺时需要用到主制部门
		// 应该考虑用位置取代
		if (operationTask.getMasterShop() == null) {
			operationTask.setMasterShop("WX");
			operationTask.setMasterShopName("外协");
		}

		// this.scheduleOperationTaskManager
		// .calcControlStart(operationTask);
		// todo
		// 下面这句话其实没什么必要，可以考虑去掉
		// log.debug(operationTask + "部门编号为:" + operationTask.getMasterShop()
		// + " 调度部门编号：" + scheme.getDeptUid());
		// if (operationTask.getMasterShop() != null
		// && operationTask.getMasterShop().indexOf(scheme.getDeptUid()) < 0) {
		// operationTask.setDeviceClass("cooperationCenter");
		// // 应该分成几类工作中心
		// operationTask.setDeviceClassName("外协中心");
		// }
		// 先设置完后再计算可选资源
		// 或者将两者结合起来

		this.calcAlterResourceList(operationTask);
		/**
		 * 计算工时
		 */
		operationTask.calTaskWork();

		operationTask.setInitialized(true);
	}

	 
	public List<SDevice> getCanDoDevices(SOperationTask operationTask) {
		List<SDevice> deviceList = new ArrayList<SDevice>();
		for (ResourceConstraint ResourceConstraint : operationTask
				.getAlterResourceMap().values()) {
			if (ResourceConstraint.getDevice() != null)
				deviceList.add(ResourceConstraint.getDevice());
		}
		return deviceList;
	}

	 
	/**
	 * 如果多能力设备
	 */
	public boolean canParallelDo(SOperationTask operationTask) {
		List<SDevice> deviceList = new ArrayList<SDevice>();
		for (ResourceConstraint ResourceConstraint : operationTask
				.getAlterResourceMap().values()) {
			// 如果是多能力设备
			if (ResourceConstraint.getDevice() != null
					&& ResourceConstraint.getDevice() instanceof McDevice)
				return true;
		}
		return false;
	}

	 
	public List<SOperationTask> getAffectTaskList(ScheduleScheme scheme,
			String taskUid) {

		SOperationTask operationTask = scheme.getAllOperationTaskMap().get(
				taskUid);

		if (operationTask == null)
			return null;

		if (operationTask.getPlanStart() == null
				|| operationTask.getPlanFinish() == null
				|| operationTask.getControlEarlyStart() == null)
			return null;

		List<SOperationTask> affectTaskList = new ArrayList<SOperationTask>();
		for (ResourceConstraint resourceConstraint : operationTask
				.getAlterResourceMap().values()) {
			for (SOperationTask affectTask : resourceConstraint.getDevice()
					.getAssignedTaskQueue()) {
				// scheduleorder是一个处于变动中的值，不能作为判断标准
				// if (affectTask.getScheduleOrder() > operationTask
				// .getScheduleOrder())
				// continue;
				if (affectTask.getPlanFinish() == null) {
					log.debug(affectTask);
				}

				if (operationTask.getControlEarlyStart().getTime()
						+ scheme.getScheduleInterval()
						* ScheduleUtils.MillSecondsOfMinute > affectTask
						.getPlanFinish().getTime())
					continue;

				if (log.isDebugEnabled()) {
					if (affectTask.getTaskUid().equals(
							"bb335e7c-3dda-47e9-9df5-97dcdc4e88d9")) {
						log.debug("aaaaa");
					}
				}
				if (affectTask.getPlanStart().getTime() > operationTask
						.getPlanFinish().getTime()
						- scheme.getScheduleInterval()
						* ScheduleUtils.MillSecondsOfMinute)
					continue;

				if (affectTask.equals(operationTask))
					continue;

				if (affectTask.getEstiTaskWork() == 0)
					continue;

				try {
					// 如果两者本来就存在链接，就不必要再显示了
					if (scheduleLinkManager.isPredTask(operationTask,
							affectTask))
						continue;
					if (scheduleLinkManager.isPredTask(affectTask,
							operationTask))
						continue;
				} catch (Exception e) {
					e.printStackTrace();
				}

				affectTaskList.add(affectTask);
			}
		}

		for (SOperationTask so : affectTaskList) {
			so.setAssnPriority(this.calAssnPriority(operationTask,
					operationTask.getDeviceUid()));
		}

		return affectTaskList;
	}

	 
	public Boolean add(Serializable object) throws BaseBusinessException {
		/**
		 * 应对有各种soperation继承类的情况
		 * 
		 * @param so
		 */
		// lqm todo
		// 如何类型精确等于呢？
		// if (object instanceof SOperationTask) {
		// return super.add(object);
		//
		// } else {
		SOperationTask p_operationTask = new SOperationTask();

		ObjectOperation.copyAttributes(object, p_operationTask);
		if (log.isDebugEnabled()) {
			log.info("**********" + p_operationTask);
		}
		return this.add(p_operationTask);
		// 可以利用同一事务自动更改功能,hql自动发sql
		// this.update(p_operationTask);
		// }
	}

	 
	public void feedbackQty(ScheduleScheme scheme,
			SOperationTask operationTask, Double completeQty, String deviceUid,
			Date workDate) throws Exception {

		if (completeQty == null || completeQty == 0)
			return;

		// todo
		// 应该放在operationTaskManager中
		// 取消2073状态，这个状态意义不大
		// operationTask.setTaskState(2073);
		operationTask.setCompleteQty(operationTask.getCompleteQty()
				+ completeQty);
		if (operationTask.getCompleteQty() < 0)
			operationTask.setCompleteQty(0d);
		if (operationTask.getCompleteQty() >= operationTask.getPlanQty()) {
			// completeTask应该允许传入workdate参数
			// todo
			operationTask.setCompleteQty(operationTask.getPlanQty());
			// 就只是注销了这句话
			// this.completeTask(scheme, operationTask);

			return;

		}
		//
		// 减少设备调整位置
		// this.changeDevice(operationTask, deviceUid);

		// 万一有负数的反馈怎么办？
		// todo
		// 允许自动回归加工时间
		if (scheme.getAllowAutoRegressHour() != null
				&& scheme.getAllowAutoRegressHour()
				&& operationTask.getDevice() != null) {

			if (operationTask.getCompleteQty() > 1 && workDate != null) {
				if (operationTask.getActualFirstFinish() != null
						&& operationTask.getActualFirstFinish()
								.before(workDate))// 如果存在首件三检
				{

					// 相差的分钟数
					// todo
					// 应该是该设备考虑日历，中断之后的时间
					// double totalrunTime= (workDate.getTime() - operationTask
					// .getActualFirstFinish().getTime()) / (60000);

					double totalrunTime = this.scheduleDeviceManager
							.getAvailableSegementCount(operationTask
									.getDevice(), operationTask
									.getActualFirstFinish(), workDate)
							* scheme.getScheduleInterval();

					// todo
					// 首件可能是多个零件
					double runtime = totalrunTime
							/ (operationTask.getCompleteQty() - 1);

					// todo
					// 应该是保留多种运行时间
					operationTask.setEstiRunTime(runtime);

				} else if (operationTask.getActualStart() != null
						&& operationTask.getActualStart().before(workDate))// 如果存在首件三检
				{

					// 相差的分钟数
					// todo
					// 应该是考虑日历，中断之后的时间
					// double totalrunTime = (workDate.getTime() - operationTask
					// .getActualStart().getTime()) / (60000);
					double totalrunTime = this.scheduleDeviceManager
							.getAvailableSegementCount(operationTask
									.getDevice(), operationTask
									.getActualStart(), workDate)
							* scheme.getScheduleInterval();

					// todo
					// 首件可能是多个零件
					double runtime = 0;

					// todo
					// 应该是保留多种运行时间
					if (totalrunTime > operationTask.getEstiPreTime()) {
						runtime = (totalrunTime - operationTask
								.getEstiPreTime())
								/ (operationTask.getCompleteQty());
					} else
						runtime = (totalrunTime)
								/ (operationTask.getCompleteQty());
					operationTask.setEstiRunTime(runtime);

				}
			}
		}

		// 重新计算剩余工时
		operationTask.calTaskWork();

		// 更新工序任务
		this.update(operationTask);

	}

	public Boolean getControlPrepareTaskInSchedule() {
		if (controlPrepareTaskInSchedule == null) {

			// lqm todo
			// 放在这里居然不起效力
			// 是不是mmutis调用时，参数还未读取到内存中呢？
			try {
//				controlPrepareTaskInSchedule = Boolean.valueOf(SysUtil
//						.getProperty("controlPrepareTaskInSchedule"));
			} catch (Exception e) {
				// TODO Auto-generated catch block
				controlPrepareTaskInSchedule = false;
			}
		}

		return controlPrepareTaskInSchedule;
	}

	 
	public void lockTask(String scheduleUid, String taskUid, Date planStart,
			Date planFinish, String deviceUid) {
		// TODO Auto-generated method stub

		try {
			ScheduleScheme scheduleScheme = ScheduleUtils
					.getScheduleScheme(scheduleUid);
			SOperationTask operationTask = scheduleScheme
					.getAllOperationTaskMap().get(taskUid);

			operationTask.setLocked(1);
			operationTask.setPlanStart(planStart);
			operationTask.setPlanFinish(planFinish);
			SDevice device = scheduleScheme.getDeviceMap().get(deviceUid);
			operationTask.setDevice(device);
			operationTask.setDeviceUid(device.getDeviceUid());

			if (!device.getDeviceClass().equals(operationTask.getDeviceClass())) {
				operationTask.setDeviceClass(device.getDeviceClass());
				operationTask.setDeviceClassName(device.getDeviceClass());
				// 缺省为本部门
				operationTask.setMasterShop(scheduleScheme.getDeptUid());
				// 应该用workcenter对象,设置mastershopname
				// todo
				// operationTask.setMasterShopName(scheme.getd)
			}

			this.update(operationTask);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	 
	public void unlockTask(String scheduleUid, String taskUid) {
		try {
			ScheduleScheme scheduleScheme = ScheduleUtils
					.getScheduleScheme(scheduleUid);
			SOperationTask operationTask = scheduleScheme
					.getAllOperationTaskMap().get(taskUid);

			operationTask.setLocked(0);
			this.update(operationTask);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	 
	public void saveMasterOperationTask(String masterScheduleUid,
			SOperationTask dataSetOpTask) throws Exception {

		if (dataSetOpTask.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
			updateOperationTask(masterScheduleUid, dataSetOpTask);
		} else {
			return;
		}
	}

	 
	public void saveCoOperationTask(String coScheduleUid,
			SOperationTask dataSetOpTask) throws Exception {

		if (dataSetOpTask.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
			updateOperationTask(coScheduleUid, dataSetOpTask);
		} else {
			return;
		}

	}

	 
	public void saveMasterCoOperationTask(String masterScheduleUid,
			String coScheduleUid, SOperationTask dataSetOpTask)
			throws Exception {

		if (dataSetOpTask.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
			updateOperationTask(masterScheduleUid, dataSetOpTask);
			updateOperationTask(coScheduleUid, dataSetOpTask);
		} else {
			return;
		}

	}

	public void updateOperationTask(String scheduleUid, SOperationTask newTask)
			throws Exception {
		log.debug("updateMasterOperationTask 开始" + newTask);
		SOperationTask originalTask = scheduleOperationTaskDao
				.getScheduleOperationTask(scheduleUid, newTask.getTaskUid());

		if (originalTask == null)
			throw new Exception("找不到更新的工序任务！" + newTask);
		if (newTask.getPlanStart() != null && newTask.getPlanFinish() != null
				&& newTask.getPlanFinish().before(newTask.getPlanStart()))
			throw new Exception("计划结束时间不能晚于计划开始时间！"
					+ newTask.toFriendlyString());

		originalTask.setEstiPreTime(newTask.getEstiPreTime());
		originalTask.setEstiRunTime(newTask.getEstiRunTime());
		// originalTask.setEstiDelayTime(newTask.getEstiDelayTime());

		log.debug("updateCooperationTask更新工序任务 开始计算可选资源列表！");
		// 因为修改工时序列，锁定，任务状态，工作中心，设备信息等都可能导致可选设备变更，所以
		// 就放在这里恒执行了
		// this.calcAlterResourceList(originalTask);
		this.update(originalTask);
		log.debug("updateMasterOperationTask 结束" + newTask);
	}

	 
	public List<SOperationTask> initDispatchTask(ScheduleScheme scheme,
			String resUid) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleOperationTaskList = scheme
				.getScheduleOperationTasks();
		for (SOperationTask opTask : scheduleOperationTaskList) {
			// 已派的任务过滤掉
			if (opTask.getManualScheduleState() != null
					&& opTask.getManualScheduleState() == SOperationTask.MANUAL_SCHEDULED) {
				continue;
			}
			// 如果resUid不是部门则需要按照工作中心过滤,先不考虑是否外协
			if (opTask.getTaskDistance() <= 10
			// && opTask.getMasterShop().equals(scheme.getDeptUid())
			// && !opTask.getDeviceClass().equals("cooperationCenter")
			) {
				if (resUid == null || resUid.equals("")
						|| resUid.equals(scheme.getDeptUid())) {
					opTaskList.add(opTask);
				} else {
					if (scheme.getWorkCenterMap().containsKey(resUid)) {
						if (opTask.getDeviceClass().equals(resUid)) {
							opTaskList.add(opTask);
						}
					}
					if (scheme.getDeviceMap().containsKey(resUid)) {
						SDevice device = scheme.getDeviceMap().get(resUid);
						if (opTask.getDeviceClass().equals(
								device.getDeviceClass())) {
							opTaskList.add(opTask);
						}
					}
				}
			}
		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {
				 
				public int compare(SOperationTask o1, SOperationTask o2) {
					// TODO Auto-generated method stub
					if (o1.getDrawingId().compareTo(o2.getDrawingId()) > 0) {
						return 1;
					} else if (o1.getDrawingId().compareTo(o2.getDrawingId()) < 0) {
						return -1;
					} else {
						if (o1.getBatchNum().compareTo(o2.getBatchNum()) > 0) {
							return 1;
						} else if (o1.getBatchNum().compareTo(o2.getBatchNum()) < 0) {
							return -1;
						} else {
							if (o1.getTaskDistance() > o2.getTaskDistance()) {
								return 1;
							} else if (o1.getTaskDistance() < o2
									.getTaskDistance()) {
								return -1;
							} else {
								return 0;
							}
						}
					}
				}
			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchReadyTaskByResUid(
			ScheduleScheme scheme, String resUid, int distance) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleOperationTaskList = scheme
				.getScheduleOperationTasks();
		/**
		 * 待派任务的逻辑是： 1、未手动排的任务； 2、虽手动排但是没有安排设备的；
		 */
		for (SOperationTask opTask : scheduleOperationTaskList) {
			if (opTask.getTaskDistance() > distance) {
				continue;
			}
			// 已派的任务过滤掉
			if (opTask.getManualScheduleState() == null
					|| opTask.getManualScheduleState() == SOperationTask.MANUAL_UNSCHEDULED) {
				if (canAdd(opTask, scheme, resUid)) {
					opTaskList.add(opTask);
				}
				/**
				 * // 已经派过的任务，其后续工序如果在resUid上，则可以派工 for (SOperationLink succLink :
				 * opTask.getSuccLinkSet()) { if (!succLink.getVirtualLink()) {
				 * SOperationTask succTask = succLink .getSuccOperationTask();
				 * if (succTask.getManualScheduleState() == null ||
				 * succTask.getManualScheduleState() ==
				 * SOperationTask.MANUAL_UNSCHEDULED) { if (canAdd(succTask,
				 * scheme, resUid)) { opTaskList.add(succTask); } } } }
				 */
			} else {
				if (opTask.getDevice() == null) {
					if (canAdd(opTask, scheme, resUid)) {
						opTaskList.add(opTask);
					}
				}
			}
		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {
				 
				public int compare(SOperationTask o1, SOperationTask o2) {
					// TODO Auto-generated method stub
					if (o1.getDrawingId().compareTo(o2.getDrawingId()) > 0) {
						return 1;
					} else if (o1.getDrawingId().compareTo(o2.getDrawingId()) < 0) {
						return -1;
					} else {
						if (o1.getBatchNum().compareTo(o2.getBatchNum()) > 0) {
							return 1;
						} else if (o1.getBatchNum().compareTo(o2.getBatchNum()) < 0) {
							return -1;
						} else {
							if (o1.getTaskDistance() > o2.getTaskDistance()) {
								return 1;
							} else if (o1.getTaskDistance() < o2
									.getTaskDistance()) {
								return -1;
							} else {
								return 0;
							}
						}
					}
				}
			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchReadyTaskBCByResUid(
			ScheduleScheme scheme, String resUid, int distance) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleOperationTaskList = scheme
				.getScheduleOperationTasks();
		SDevice device = scheme.getDeviceMap().get(resUid);
		for (SOperationTask opTask : scheduleOperationTaskList) {
			if (opTask.getTaskDistance() > distance) {
				continue;
			}
			// 此时的任务已经派到设备上，所以应该按照设备过滤,也应包括工艺定义的工作中心包含当前设备的任务
			if ((opTask.getDeviceUid() != null && resUid.equals(opTask
					.getDeviceUid()))
					|| (opTask.getDeviceUid() == null && opTask
							.getDeviceClass().equals(device.getDeviceClass()))) {
				opTaskList.add(opTask);
			}
		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {
				 
				public int compare(SOperationTask o1, SOperationTask o2) {
					// TODO Auto-generated method stub
					if (o1.getDrawingId().compareTo(o2.getDrawingId()) > 0) {
						return 1;
					} else if (o1.getDrawingId().compareTo(o2.getDrawingId()) < 0) {
						return -1;
					} else {
						if (o1.getBatchNum().compareTo(o2.getBatchNum()) > 0) {
							return 1;
						} else if (o1.getBatchNum().compareTo(o2.getBatchNum()) < 0) {
							return -1;
						} else {
							if (o1.getTaskDistance() > o2.getTaskDistance()) {
								return 1;
							} else if (o1.getTaskDistance() < o2
									.getTaskDistance()) {
								return -1;
							} else {
								return 0;
							}
						}
					}
				}
			});
		}
		return opTaskList;
	}

	private boolean canAdd(SOperationTask opTask, ScheduleScheme scheme,
			String resUid) {
		if (resUid == null || resUid.equals("")
				|| resUid.equals(scheme.getDeptUid())) {
			return true;
		} else {
			if (scheme.getWorkCenterMap().containsKey(resUid)) {
				if (opTask.getDeviceClass().equals(resUid)) {
					return true;
				}
			}
			if (scheme.getDeviceMap().containsKey(resUid)) {
				SDevice device = scheme.getDeviceMap().get(resUid);
				if (opTask.getDeviceClass().equals(device.getDeviceClass())) {
					return true;
				}
			}
		}
		// TODO Auto-generated method stub
		return false;
	}

	 
	public List<SOperationTask> initDispatchTaskByTaskUid(
			ScheduleScheme scheme, String taskUid) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		if (taskUid == null || taskUid.equals("")) {
			return opTaskList;
		}
		SPartTask partTask = scheme.getAllPartTaskMap().get(taskUid);
		if (partTask == null) {
			log.error("无法找到对应的零件任务！" + taskUid);
			return null;
		}
		for (SOperationTask opTask : partTask.getOperationTaskList()) {
			if (opTask.getManualScheduleState() != null
					&& opTask.getManualScheduleState() == SOperationTask.MANUAL_SCHEDULED) {
				continue;
			}
			if (opTask.getTaskDistance() <= 3
					&& opTask.getMasterShop().equals(scheme.getDeptUid())
					&& !opTask.getDeviceClass().equals("cooperationCenter")) {
				opTaskList.add(opTask);
			}
		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {
				 
				public int compare(SOperationTask o1, SOperationTask o2) {
					// TODO Auto-generated method stub
					if (o1.getTaskDistance() > o2.getTaskDistance()) {
						return 1;
					}
					if (o1.getTaskDistance() < o2.getTaskDistance()) {
						return -1;
					}
					return 0;
				}
			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchedTask(ScheduleScheme scheme) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleOperationTaskList = scheme
				.getScheduleOperationTasks();
		for (SOperationTask opTask : scheduleOperationTaskList) {

			// if (opTask.getManualScheduleState() != null
			// && opTask.getManualScheduleState() ==
			// SOperationTask.MANUAL_SCHEDULED) {
			if (opTask.getTaskDistance() <= 7
					&& opTask.getMasterShop().equals(scheme.getDeptUid())
					&& !opTask.getDeviceClass().equals("cooperationCenter")
					&& !opTask.getDeviceUid().equals("cooperation")) {
				opTaskList.add(opTask);
			}
			// }
		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {
				 
				public int compare(SOperationTask o1, SOperationTask o2) {
					// TODO Auto-generated method stub
					if (o1.getTaskDistance() > o2.getTaskDistance()) {
						return 1;
					}
					if (o1.getTaskDistance() < o2.getTaskDistance()) {
						return -1;
					}
					return 0;
				}
			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchedTaskByResUid(
			ScheduleScheme scheme, String resUid) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleOperationTaskList = scheme
				.getScheduleOperationTasks();
		for (SOperationTask opTask : scheduleOperationTaskList) {
			if (opTask.getManualScheduleState() != null
					&& opTask.getManualScheduleState() == SOperationTask.MANUAL_SCHEDULED) {
				// 如果resUid为工作中心
				if ("cooperationCenter".equals(resUid)
						&& opTask.getWorkCenterUid().equals(resUid)) {
					opTaskList.add(opTask);
				} else if (scheme.getWorkCenterMap().containsKey(resUid)) {
					List<SDevice> deviceList = scheme.getWorkCenterMap().get(
							resUid).getSDeviceList();
					for (SDevice device : deviceList) {
						if (device.getDeviceUid().equals(opTask.getDeviceUid())) {
							opTaskList.add(opTask);
							break;
						}
					}
				}
				// 如果是设备
				else if (scheme.getDeviceMap().containsKey(resUid)) {
					SDevice device = scheme.getDeviceMap().get(resUid);
					if (device.getDeviceUid().equals(opTask.getDeviceUid())) {
						opTaskList.add(opTask);
					}
				}
				// 如果是在部门下
				if (resUid == null || resUid.equals("")) {
					opTaskList.add(opTask);
				}
			}
		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {
				 
				public int compare(SOperationTask o1, SOperationTask o2) {
					// TODO Auto-generated method stub
					if (o1.getTaskDistance() > o2.getTaskDistance()) {
						return 1;
					}
					if (o1.getTaskDistance() < o2.getTaskDistance()) {
						return -1;
					}
					return 0;
				}
			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchedTaskByTaskUid(
			ScheduleScheme scheme, String taskUid) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		if (taskUid == null || taskUid.equals("")) {
			// 表示取全部的工序任务作为零件任务日历的展示
			return opTaskList;
		}
		SPartTask partTask = scheme.getAllPartTaskMap().get(taskUid);
		if (partTask != null) {
			for (SOperationTask opTask : partTask.getOperationTaskList()) {
				if (opTask.getManualScheduleState() != null
						&& opTask.getManualScheduleState() == SOperationTask.MANUAL_SCHEDULED) {
					// 不关心工序距离和主制
					// if (opTask.getTaskDistance() <= 3
					// && opTask.getMasterShop().equals(scheme.getDeptUid())
					// && !opTask.getDeviceClass().equals("cooperationCenter")
					// && !opTask.getDeviceUid().equals("cooperation")) {
					opTaskList.add(opTask);
					// }
				}
			}
		}

		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {

				 
				public int compare(SOperationTask o1, SOperationTask o2) {

					// TODO Auto-generated method stub
					if (o1.getTaskDistance() > o2.getTaskDistance()) {
						return 1;
					}
					if (o1.getTaskDistance() < o2.getTaskDistance()) {
						return -1;
					}
					return 0;
				}

			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initAllDispatchedTaskByTaskUid(
			ScheduleScheme scheme, String taskUid) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		if (taskUid == null || taskUid.equals("")) {
			return opTaskList;
		}
		SPartTask partTask = scheme.getAllPartTaskMap().get(taskUid);
		if (partTask != null) {
			for (SOperationTask opTask : partTask.getOperationTaskList()) {
				opTaskList.add(opTask);
			}
		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {

				 
				public int compare(SOperationTask o1, SOperationTask o2) {

					// TODO Auto-generated method stub
					if (o1.getTaskDistance() > o2.getTaskDistance()) {
						return 1;
					}
					if (o1.getTaskDistance() < o2.getTaskDistance()) {
						return -1;
					}
					return 0;
				}

			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchReadyTaskByTaskUid(
			ScheduleScheme scheme, String taskUid) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		if (taskUid == null || taskUid.equals("")) {
			return opTaskList;
		}
		SPartTask partTask = scheme.getAllPartTaskMap().get(taskUid);
		if (partTask != null) {
			for (SOperationTask opTask : partTask.getOperationTaskList()) {
				// 取出对应零件任务的所有未派的工序,但如果工序没有设备，也返回
				if (opTask.getManualScheduleState() != null
						&& opTask.getManualScheduleState() == SOperationTask.MANUAL_SCHEDULED
				/* && opTask.getDevice() != null */) {
					continue;
				}
				opTaskList.add(opTask);
			}
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchNextTask(ScheduleScheme scheme,
			SOperationTask operationTask, String resUid) {
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		SOperationTask succOperation = new SOperationTask();
		Set<SOperationLink> succLinkSet = operationTask.getSuccLinkSet();
		for (SOperationLink succLink : succLinkSet) {
			if (!succLink.getVirtualLink()) {
				succOperation = succLink.getSuccOperationTask();
				break;
			}
		}
		// 如果后置任务(要求未派)不能出现在resUid加工，则也不出现
		if (succOperation.getTaskUid() != null
				&& (succOperation.getManualScheduleState() == null || succOperation
						.getManualScheduleState() == SOperationTask.MANUAL_UNSCHEDULED))
			if (canAdd(succOperation, scheme, resUid)) {
				opTaskList.add(succOperation);
			}
		// TODO Auto-generated method stub
		return opTaskList;
	}

	 
	public List<SOperationTask> initDispatchedAllTaskByResUid(
			ScheduleScheme scheme, String resUid) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleOperationTaskList = scheme
				.getScheduleOperationTasks();
		for (SOperationTask opTask : scheduleOperationTaskList) {

			// 如果resUid为工作中心
			if (scheme.getWorkCenterMap().containsKey(resUid)) {
				List<SDevice> deviceList = scheme.getWorkCenterMap()
						.get(resUid).getSDeviceList();
				for (SDevice device : deviceList) {
					if (device.getDeviceUid().equals(opTask.getDeviceUid())) {
						opTaskList.add(opTask);
						break;
					}
				}
			}
			// 如果是设备
			else if (scheme.getDeviceMap().containsKey(resUid)) {
				SDevice device = scheme.getDeviceMap().get(resUid);
				if (device.getDeviceUid().equals(opTask.getDeviceUid())) {
					opTaskList.add(opTask);
				}
			}
			// 如果是在部门下
			if (resUid == null || resUid.equals("")) {
				opTaskList.add(opTask);
			}

		}
		if (opTaskList.size() > 0) {
			Collections.sort(opTaskList, new Comparator<SOperationTask>() {
				 
				public int compare(SOperationTask o1, SOperationTask o2) {
					// TODO Auto-generated method stub
					if (o1.getTaskDistance() > o2.getTaskDistance()) {
						return 1;
					}
					if (o1.getTaskDistance() < o2.getTaskDistance()) {
						return -1;
					}
					return 0;
				}
			});
		}
		return opTaskList;
	}

	 
	public List<SOperationTask> initPartTaskByTaskUid(ScheduleScheme scheme,
			String taskUid, String allPartTask, String isCriticalOp,
			String allTask) {
		// TODO Auto-generated method stub
		List<SOperationTask> opTaskList = new ArrayList<SOperationTask>();
		Set<SOperationTask> scheduleOperationTaskList = scheme
				.getScheduleOperationTasks();
		for (SOperationTask operationTask : scheduleOperationTaskList) {
			if (allPartTask.equals("true")) {
				if (isCriticalOp.equals("true")) {
					if (operationTask.getWorkCenterUid() == null
							|| operationTask.getWorkCenterUid().equals("")) {
						continue;
					}
					SWorkCenter workCenter = scheme.getWorkCenterMap().get(
							operationTask.getWorkCenterUid());
					// 0，1，2，6
					if (workCenter == null
							|| workCenter.getCriticalLevel() >= 2) {
						continue;
					}
				}
				if (allTask.equals("false")) {
					if (operationTask.getManualScheduleState() == null
							|| operationTask.getManualScheduleState() != SOperationTask.MANUAL_SCHEDULED) {
						continue;
					}
				}
				opTaskList.add(operationTask);
			} else {
				if (operationTask.getParentTask() != null
						&& operationTask.getParentTaskUid().equals(taskUid)) {
					if (isCriticalOp.equals("true")) {
						// 0，1，2，6
						if (operationTask.getWorkCenterUid() == null
								|| operationTask.getWorkCenterUid().equals("")) {
							continue;
						}
						SWorkCenter workCenter = scheme.getWorkCenterMap().get(
								operationTask.getWorkCenterUid());
						// 0，1，2，6
						if (workCenter == null
								|| workCenter.getCriticalLevel() >= 2) {
							continue;
						}
					}
					if (allTask.equals("false")) {
						if (operationTask.getManualScheduleState() == null
								|| operationTask.getManualScheduleState() != SOperationTask.MANUAL_SCHEDULED) {
							continue;
						}
					}
					opTaskList.add(operationTask);
				}
			}
		}
		return opTaskList;
	}

	@Override
	public List<SOperationTask> getMustDoList(SWorkCenter workCenter, Date analyseStart, Date analyseFinish,
			Double slackFactor, String drawingId, Integer maxTaskInstance) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<SOperationTask> getOperationTaskListForShiftProduction(ScheduleScheme scheme, String taskUid)
			throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<SOperationTask> getDragedOperationTask(String scheduleUid) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	 

}
